一、什么是装饰器模式?
装饰器模式(Decorator Pattern)是一种结构型设计模式 ,它允许你在不修改现有对象结构 的情况下,动态地为对象添加新的功能。它通过将对象包装在一个"装饰器"对象中来实现,这个装饰器对象提供了与原对象相同的接口,并增加了额外的行为。
二、装饰器模式的核心组件
- 组件 (Component):定义了原始对象和装饰器对象的共同接口。客户端代码将通过这个接口与所有对象(无论是否被装饰)进行交互。
- 具体组件 (Concrete Component):这是我们要装饰的原始对象,它实现了组件接口。
- 基础装饰器 (Base Decorator):一个抽象类,它也实现了组件接口。它内部持有一个对另一个"组件"对象的引用(可以是具体组件,也可以是另一个装饰器)。它的主要职责是将所有请求转发给被包装的对象。
- 具体装饰器 (Concrete Decorator):继承自基础装饰器,负责为组件添加特定的新功能。它会在转发请求之前或之后执行自己的附加逻辑。
三、示例:打造一个多渠道通知器
3.1 定义组件接口 (Component)
这是所有通知器都必须遵守的契约。
typescript
// Component: 通知器的统一接口
interface INotifier {
send(message: string): void;
}
3.2 创建具体组件 (Concrete Component)
这是我们的基础,最核心的通知功能。
typescript
// Concrete Component: 基础通知器,只打印到控制台
class BaseNotifier implements INotifier {
send(message: string): void {
console.log(`[站内信]:发送消息 - "${message}"`);
}
}
3.3 创建基础装饰器 (Base Decorator)
这个抽象类是所有装饰器的父类,它负责"包装"和"代理"。
typescript
// Base Decorator: 装饰器基类
abstract class NotifierDecorator implements INotifier {
protected wrappedNotifier: INotifier;
constructor(notifier: INotifier) {
this.wrappedNotifier = notifier;
}
// 将 send 请求委托给被包装的对象
send(message: string): void {
this.wrappedNotifier.send(message);
}
}
3.4. 创建具体装饰器 (Concrete Decorators)
现在来制作我们的实际业务:发送短信和邮件
typescript
// Concrete Decorator 1: 短信通知装饰器
class SMSDecorator extends NotifierDecorator {
send(message: string): void {
super.send(message); // 首先调用原始的 send 方法
console.log(`[短信]:发送消息 - "${message}"`);
}
}
// Concrete Decorator 2: 邮件通知装饰器
class EmailDecorator extends NotifierDecorator {
send(message: string): void {
super.send(message); // 调用原始方法
console.log(`[邮件]:发送消息 - "${message}"`);
}
}
注意 super.send(message)
的调用,它确保了包装链上的原始功能得以执行。你也可以把自己的逻辑放在它前面,实现前置处理。
3.5 自由组合,动态增强!
现在,我们可以像搭积木一样,自由地组合这些功能。
typescript
const message = '您的订单已发货!';
// 1. 只需要一个基础通知器
console.log('--- 基础通知 ---');
const basicNotifier = new BaseNotifier();
basicNotifier.send(message);
console.log('\n' + '='.repeat(30) + '\n');
// 2. 我需要站内信 + 短信
console.log('--- 站内信 + 短信 ---');
let notifierWithSMS = new BaseNotifier();
notifierWithSMS = new SMSDecorator(notifierWithSMS);
notifierWithSMS.send(message);
console.log('\n' + '='.repeat(30) + '\n');
// 3. 我需要站内信 + 短信 + 邮件
console.log('--- 站内信 + 短信 + 邮件 ---');
let notifierWithAll = new BaseNotifier();
notifierWithAll = new SMSDecorator(notifierWithAll);
notifierWithAll = new EmailDecorator(notifierWithAll);
notifierWithAll.send(message);
console.log('\n' + '='.repeat(30) + '\n');
// 4. 还可以有更疯狂的组合:站内信 + 邮件 + 再次短信(如果业务需要)
console.log('--- 疯狂组合 ---');
let crazyNotifier: INotifier = new BaseNotifier();
crazyNotifier = new EmailDecorator(crazyNotifier);
crazyNotifier = new SMSDecorator(crazyNotifier);
crazyNotifier.send('系统即将维护,请注意!');
运行结果:
ini
--- 基础通知 ---
[站内信]:发送消息 - "您的订单已发货!"
==============================
--- 站内信 + 短信 ---
[站内信]:发送消息 - "您的订单已发货!"
[短信]:发送消息 - "您的订单已发货!"
==============================
--- 站内信 + 短信 + 邮件 ---
[站内信]:发送消息 - "您的订单已发货!"
[短信]:发送消息 - "您的订单已发货!"
[邮件]:发送消息 - "您的订单已发货!"
==============================
--- 疯狂组合 ---
[站内信]:发送消息 - "系统即将维护,请注意!"
[邮件]:发送消息 - "系统即将维护,请注意!"
[短信]:发送消息 - "系统即将维护,请注意!"
为了方便大家学习和实践,本文的所有示例代码和完整项目结构都已整理上传至我的 GitHub 仓库。欢迎大家克隆、研究、提出 Issue,共同进步!
📂 核心代码与完整示例: GoF
总结
如果你喜欢本教程,记得点赞+收藏!关注我获取更多JavaScript/TypeScript开发干货