装饰器模式核心概念
- 装饰器模式:
- (Decorator Pattern) 是一种结构型设计模式,核心思想是:在不修改原有对象代码的前提下,动态地给对象添加额外的功能;
- 它通过 “包装” 原有对象的方式扩展功能,比继承更灵活 (避免类爆炸),符合 “开闭原则” (对扩展开放,对修改关闭);
- 类图:
- 实现代码:
// -------------------------- 1. Component(抽象组件:MilkTea)-------------------------- // TS 抽象类,完全匹配类图中的 MilkTea 抽象组件 abstract class MilkTea { // 抽象方法(类图中标注 * 的 operation 方法),强制子类实现 public abstract operation(): number; } // -------------------------- 2. ConcreteComponent(具体组件:BasicMilkTea)------------- // 基础奶茶类,继承抽象类 MilkTea,实现核心方法 class BasicMilkTea extends MilkTea { // 实现抽象方法:返回基础奶茶价格(类型注解:返回值为 number) public operation(): number { return 10; } } // -------------------------- 3. Decorator(抽象装饰器:MilkTeaDecorator)--------------- abstract class MilkTeaDecorator extends MilkTea { // 类图中标注的 milkTea 属性,TS 显式声明类型为 MilkTea protected milkTea: MilkTea; // 构造函数接收 MilkTea 实例,约束参数类型 constructor(milkTea: MilkTea) { super(); this.milkTea = milkTea; } // 抽象方法,强制子类实现(匹配类图中的 * 标记) public abstract operation(): number; } // -------------------------- 4. ConcreteDecoratorA(具体装饰器:PearlDecorator)---------- // 珍珠装饰器,继承抽象装饰器 class PearlDecorator extends MilkTeaDecorator { // 实现抽象方法:基础价格 + 珍珠加价 public operation(): number { return this.milkTea.operation() + 2; } } // -------------------------- 5. ConcreteDecoratorB(具体装饰器:CheeseFoamDecorator)------ // 奶盖装饰器,继承抽象装饰器 class CheeseFoamDecorator extends MilkTeaDecorator { // 实现抽象方法:基础价格 + 奶盖加价 public operation(): number { return this.milkTea.operation() + 3; } } // -------------------------- 测试代码(带类型校验)-------------------------- // 1. 基础奶茶 const basicTea: MilkTea = new BasicMilkTea(); console.log("基础奶茶价格:", basicTea.operation()); // 输出:10 // 2. 基础奶茶 + 珍珠(装饰器包装) const teaWithPearl: MilkTea = new PearlDecorator(basicTea); console.log("基础奶茶+珍珠价格:", teaWithPearl.operation()); // 输出:12 // 3. 基础奶茶 + 珍珠 + 奶盖(多层装饰) const teaWithPearlAndFoam: MilkTea = new CheeseFoamDecorator(teaWithPearl); console.log("基础奶茶+珍珠+奶盖价格:", teaWithPearlAndFoam.operation()); // 输出:15 // 4. 基础奶茶 + 奶盖 const teaWithFoam: MilkTea = new CheeseFoamDecorator(basicTea); console.log("基础奶茶+奶盖价格:", teaWithFoam.operation()); // 输出:13
常用使用场景
ES7 装饰器语法
- 日志 / 性能监控:给函数添加日志打印、耗时统计,不修改函数逻辑;
- 实现代码:
// 日志装饰器示例 function logDecorator(target, name, descriptor) { const originalFn = descriptor.value; descriptor.value = function(...args) { console.log(`调用函数 ${name},参数:`, args); const result = originalFn.apply(this, args); console.log(`函数 ${name} 返回值:`, result); return result; }; return descriptor; } class Calculator { @logDecorator add(a, b) { return a + b; } } const calc = new Calculator(); calc.add(1, 2); // 自动打印日志,不修改 add 逻辑
Axios 拦截器
- Axios 的请求 / 响应拦截器本质是装饰器模式,拦截器函数,动态给请求添加 token、请求头、错误处理,不修改核心请求逻辑;
- 实现代码:
// 请求拦截器(装饰请求) axios.interceptors.request.use( config => { // 扩展功能:添加 token config.headers.Authorization = "Bearer " + localStorage.getItem("token"); return config; // 原请求对象被装饰后返回 }, error => Promise.reject(error) ); // 响应拦截器(装饰响应) axios.interceptors.response.use( response => { // 扩展功能:统一处理响应数据 return response.data; }, error => { // 扩展功能:统一处理错误 console.log("请求失败:", error); return Promise.reject(error); } );
UI 组件动态扩展
- React 高阶组件 (HOC) 是装饰器模式的典型应用,HOC 函数 (如 withLoading、withAuth),动态给组件添加加载状态、权限控制
- 实现代码:
// 加载状态装饰器(HOC) function withLoading(Component) { return function(props) { if (props.isLoading) { return <div>加载中...</div>; } return <Component {...props} />; // 原组件被装饰后返回 }; } // 基础按钮组件 const Button = ({ text }) => <button>{text}</button>; // 装饰后:带加载状态的按钮 const ButtonWithLoading = withLoading(Button); // 使用:<ButtonWithLoading text="提交" isLoading={true} />
权限控制装饰器
- 实现代码:
// 角色类型 type UserRole = 'admin' | 'user' | 'guest'; // 按钮接口 interface Button { render(role?: UserRole): string; } // 基础按钮 class BaseButton implements Button { render(): string { return '<button>点击</button>'; } } // 权限装饰器 class AuthDecorator implements Button { constructor( private button: Button, private requiredRole: UserRole ) {} render(currentUserRole?: UserRole): string { if (currentUserRole === this.requiredRole) { return this.button.render(); } return '<button disabled>无权限</button>'; } } // 使用示例 const button = new BaseButton(); const adminButton = new AuthDecorator(button, 'admin'); console.log(adminButton.render('user')); // 输出禁用按钮 console.log(adminButton.render('admin')); // 输出正常按钮
装饰器模式优缺点
优点
- 动态扩展对象功能,符合开闭原则;
- 比继承更灵活,避免类爆炸;
- 可以组合多个装饰器;
- 装饰器和被装饰对象可以独立变化;
缺点
- 增加系统复杂度;
- 多层装饰会增加调试难度;
- 可能产生大量小对象;
适用场景
- 需要动态、透明地给对象添加职责;
- 需要扩展功能但不想修改原有类;
- 需要大量独立功能的组合;
- 不想使用继承导致子类过多的情况;
适配器模式(结构型模式)
上一篇