【TS 设计模式完全指南】TypeScript 装饰器模式的优雅之道

一、什么是装饰器模式?

装饰器模式(Decorator Pattern)是一种结构型设计模式 ,它允许你在不修改现有对象结构 的情况下,动态地为对象添加新的功能。它通过将对象包装在一个"装饰器"对象中来实现,这个装饰器对象提供了与原对象相同的接口,并增加了额外的行为。

二、装饰器模式的核心组件

  1. 组件 (Component):定义了原始对象和装饰器对象的共同接口。客户端代码将通过这个接口与所有对象(无论是否被装饰)进行交互。
  2. 具体组件 (Concrete Component):这是我们要装饰的原始对象,它实现了组件接口。
  3. 基础装饰器 (Base Decorator):一个抽象类,它也实现了组件接口。它内部持有一个对另一个"组件"对象的引用(可以是具体组件,也可以是另一个装饰器)。它的主要职责是将所有请求转发给被包装的对象。
  4. 具体装饰器 (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开发干货

相关推荐
一个很帅的帅哥15 小时前
Vue keep-alive
前端·javascript·vue.js·keep-alive
lbh15 小时前
Chrome DevTools 详解(一):Elements 面板
前端·javascript·浏览器
明里人15 小时前
React 状态库:Zustand 和 Jotai 怎么选?
前端·javascript·react.js
儒雅的烤地瓜16 小时前
JS | 如何把一个伪数组转换成一个真正的数组?
javascript·from方法·数组转换·扩展运算符·slice方法·push方法
β添砖java17 小时前
交互动效设计
前端·javascript·交互
1710orange17 小时前
java设计模式:动态代理
java·开发语言·设计模式
简小瑞17 小时前
VSCode用它管理上千个服务:依赖注入从入门到实战
前端·设计模式
用户561706571114718 小时前
scratch二次开发--如何在舞台区开启网络摄像头(Turbowarp版)
javascript
进阶的鱼18 小时前
React+ts+vite脚手架搭建(三)【状态管理篇】
前端·javascript·react.js
charlie11451419119 小时前
精读C++20设计模式——结构型设计模式:外观模式
c++·学习·设计模式·c++20·外观模式