TypeScript 设计模式之【装饰模式】

文章目录

装饰模式:为你的对象穿上华丽的外衣

嘿程序员,你有一件普通格子衬衫,它很舒适,但有时候你可能想让它看起来更特别一些。你可以给它加上一些别针、徽章或者刺绣,让它变得与众不同。

这就像是在编程中使用装饰模式,你可以在不改变原始对象的情况下,为它添加新的功能或者修改它的行为。装饰模式就像是一位时尚设计师,能够为你的对象设计出各种华丽的"外衣"!

装饰者的魔法

装饰模式就像是给你的对象穿上一层又一层的"衣服",每一层都可以添加新的功能或者修改现有的行为,而且你可以随时添加或移除这些"衣服",非常灵活。

装饰模式有什么利与害?

装饰模式的优点是它可以在不修改原始代码的情况下扩展对象的功能,就像你可以给衬衫添加各种装饰而不需要改变衬衫本身。它遵循开闭原则,对扩展开放,对修改关闭。缺点是如果过度使用,会导致代码中出现大量小对象,使系统变得复杂难懂。

如何使用装饰者来美化你的对象

装饰涉及角色

  • 组件(Component):定义可以动态添加职责的对象的接口

  • 具体组件(ConcreteComponent):定义可以添加额外职责的对象

  • 装饰(Decorator):维持一个指向Component对象的引用,并定义一个与Component接口一致的接口。

  • 具体装饰(ConcreteDecorator):向组件添加职责。

装饰步骤

  1. 创建一个基础组件接口

  2. 实现具体的基础组件

  3. 创建一个装饰器基类,实现了组件接口并包含一个组件引用

  4. 创建具体的装饰器类,继承自装饰器基类并添加新的行为

  5. 使用这些装饰器来包装组件,从而动态地添加新的功能

选择合适的装饰器,你就能轻松地为你的对象添加各种功能,让它变得更加强大和灵活!

代码实现案例

typescript 复制代码
// 组件接口-衬衫
interface Shirt {
  // 获取外表   
  getDescription(): string;
  // 获取成本
  getCost(): number;
}

// 具体组件-普通衬衫
class BasicShirt implements Shirt {
  getDescription(): string {
    return "普通格子衬衫";
  }
  getCost(): number {
    return 100;
  }
}

// 装饰器基类
abstract class ShirtDecorator implements Shirt {
  protected shirt: Shirt;

  constructor(shirt: Shirt) {
    this.shirt = shirt;
  }

  getDescription(): string {
    return this.shirt.getDescription();
  }

  getCost(): number {
    return this.shirt.getCost();
  }
}

// 具体装饰器:别针
class PinDecorator extends ShirtDecorator {
  getDescription(): string {
    return `${this.shirt.getDescription()}, 加上别针`;
  }

  getCost(): number {
    return this.shirt.getCost() + 20;
  }
}

// 具体装饰器:徽章
class BadgeDecorator extends ShirtDecorator {
  getDescription(): string {
    return `${this.shirt.getDescription()}, 加上徽章`;
  }

  getCost(): number {
    return this.shirt.getCost() + 15;
  }
}

// 具体装饰器:刺绣
class EmbroideryDecorator extends ShirtDecorator {
  getDescription(): string {
    return `${this.shirt.getDescription()}, 加上刺绣`;
  }

  getCost(): number {
    return this.shirt.getCost() + 50;
  }
}

// 使用装饰器
let shirt: Shirt = new BasicShirt();
console.log(shirt.getDescription()); // 输出: 普通格子衬衫
console.log(shirt.getCost()); // 输出: 100

shirt = new PinDecorator(shirt);
console.log(shirt.getDescription()); // 输出: 普通格子衬衫, 加上别针
console.log(shirt.getCost()); // 输出: 120

shirt = new BadgeDecorator(shirt);
console.log(shirt.getDescription()); // 输出: 普通格子衬衫, 加上别针, 加上徽章
console.log(shirt.getCost()); // 输出: 135

shirt = new EmbroideryDecorator(shirt);
console.log(shirt.getDescription()); // 输出: 普通格子衬衫, 加上别针, 加上徽章, 加上刺绣
console.log(shirt.getCost()); // 输出: 185

装饰模式的主要优点

  1. 灵活性强:通过组合不同的装饰器来创建各种不同的行为

  2. 遵循开闭原则:在不修改现有代码的情况下添加新的功能

  3. 比继承更加灵活:动态地添加或删除职责,而不是在编译时就确定

  4. 支持递归组合:用多个装饰器包装一个组件

装饰模式的主要缺点

  1. 可能会创建很多小对象:每个装饰器都是一个新的对象,如果过度使用可能会导致系统变得复杂。
  2. 装饰层次增多时会更复杂:如果有太多的装饰类,或许会让系统变得难以理解和维护
  3. 可能会导致错误配置:由于可以动态地添加装饰器,或许会因为错误的配置导致意外的行为

装饰模式的适用场景

  1. 需要在运行时动态地给对象添加额外的职责,而不希望改变原有对象的结构
  2. 希望通过组合而不是继承来扩展对象的功能
  3. 系统中有大量独立的扩展,为支持每种组合将产生大量的子类,使得子类数目呈爆炸性增长。

总结

装饰模式是一种结构型设计模式,它允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。这种模式在不修改现有对象结构的情况下动态地扩展对象的功能,它具有很强的灵活性和可扩展性,但也会导致系统中出现大量小对象。合理使用装饰模式,可以让你的代码更加灵活,更易于维护和扩展。

喜欢的话就点个赞 ❤️,关注一下吧,有问题也欢迎讨论指教。感谢大家!!!

下期预告:TypeScript 设计模式之【外观模式】

相关推荐
一袋米扛几楼9811 分钟前
【网络安全】SIEM -Security Information and Event Management 工具是什么?
前端·安全·web安全
小陈工23 分钟前
2026年4月7日技术资讯洞察:下一代数据库融合、AI基础设施竞赛与异步编程实战
开发语言·前端·数据库·人工智能·python
Cobyte32 分钟前
3.响应式系统基础:从发布订阅模式的角度理解 Vue2 的数据响应式原理
前端·javascript·vue.js
竹林81835 分钟前
从零到一:在React前端中集成The Graph查询Uniswap V3池数据实战
前端·javascript
Mintopia42 分钟前
别再迷信"优化":大多数性能问题根本不在代码里
前端
倾颜43 分钟前
接入 MCP,不一定要先平台化:一次 AI Runtime 的实战取舍
前端·后端·mcp
军军君011 小时前
Three.js基础功能学习十八:智能黑板实现实例五
前端·javascript·vue.js·3d·typescript·前端框架·threejs
恋猫de小郭1 小时前
Android 上为什么主题字体对 Flutter 不生效,对 Compose 生效?Flutter 中文字体问题修复
android·前端·flutter
Moment1 小时前
AI全栈入门指南:一文搞清楚NestJs 中的 Controller 和路由
前端·javascript·后端
禅思院1 小时前
前端架构演进:基于AST的常量模块自动化迁移实践
前端·vue.js·前端框架