前端开发设计模式——装饰器模式

目录

一、装饰器模式的定义和特点

1.定义

2.特点

二、装饰器模式的实现方式

1.在原生JS中实现(以类的形式为例)

2、在Vue中实现(以指令和混入为例)

2.1、指令方式实现装饰功能

2.2、混入方式实现装饰功能

三、装饰器模式的使用场景

1.用户界面增强

2.权限管理

3.数据处理与展示

四、装饰器模式的优点

1.灵活性

2.遵循开闭原则

3.单一职责原则的体现

五、装饰器模式的缺点

1.增加复杂性

2.可能影响性能

六、装饰器模式的注意事项

1.接口的稳定性

2.避免过度装饰

3.装饰器顺序


一、装饰器模式的定义和特点

1.定义

装饰器模式是一种结构型设计模式,它允许在不改变对象结构的情况下,动态地给一个对象添加一些额外的功能。这个模式通过创建装饰类来包装原始对象,装饰类与原始对象实现相同的接口,从而可以在运行时根据需要组合不同的装饰类来扩展对象的功能。

2.特点

保持接口一致性:装饰类和被装饰类实现相同的接口,这样在使用装饰后的对象时,对于客户端来说,它看起来仍然是原始类型的对象,客户端代码不需要进行修改就可以使用被装饰后的对象。

动态扩展性:可以在运行时动态地添加或移除装饰,根据不同的需求灵活组合装饰类,以实现不同的功能组合。

单一职责原则:每个装饰类都专注于一个特定的功能扩展,这样代码的可维护性和可读性更高。

二、装饰器模式的实现方式

1.在原生JS中实现(以类的形式为例)

(1)首先定义一个基础接口或者抽象类(在 JavaScript 中可以使用抽象类的概念来模拟)。例如,定义一个 Component 抽象类表示可被装饰的组件:

javascript 复制代码
   class Component {
       operation() {
           throw new Error('Abstract method must be implemented');
       }
   }

(2)然后创建一个具体的组件类实现这个接口,例如 ConcreteComponent:

javascript 复制代码
   class ConcreteComponent extends Component {
       operation() {
           console.log('ConcreteComponent operation');
       }
   }

(3)接着定义装饰器类,装饰器类也继承自 Component 抽象类,并且在构造函数中接收一个 Component 类型的实例,例如 Decorator:

javascript 复制代码
   class Decorator extends Component {
       constructor(component) {
           super();
           this.component = component;
       }

       operation() {
           this.component.operation();
       }
   }

(4)最后创建具体的装饰器类,例如 ConcreteDecoratorAConcreteDecoratorB,它们在 operation 方法中添加额外的功能:

javascript 复制代码
   class ConcreteDecoratorA extends Decorator {
       operation() {
           console.log('ConcreteDecoratorA before operation');
           super.operation();
           console.log('ConcreteDecoratorA after operation');
       }
   }

   class ConcreteDecoratorB extends Decorator {
       operation() {
           console.log('ConcreteDecoratorB before operation');
           super.operation();
           console.log('ConcreteDecoratorB after operation');
       }
   }

(5)使用方式如下:

javascript 复制代码
   const component = new ConcreteComponent();
   const decoratedComponentA = new ConcreteDecoratorA(component);
   const decoratedComponentAB = new ConcreteDecoratorB(decoratedComponentA);
   decoratedComponentAB.operation();

2、在Vue中实现(以指令和混入为例)

2.1、指令方式实现装饰功能

假设我们有一个基础的 Vue 组件,例如一个简单的按钮组件:

javascript 复制代码
   <template>
       <button @click="handleClick">Base Button</button>
   </template>

   <script>
   export default {
       methods: {
           handleClick() {
               console.log('Button clicked');
           }
       }
   };
   </script>

我们可以创建一个指令来装饰这个按钮组件,例如给按钮添加权限验证功能的指令。首先定义指令:

javascript 复制代码
   Vue.directive('permission - check', {
       inserted: function (el, binding) {
           // 假设这里有一个权限验证逻辑,比如根据用户权限角色判断是否有点击按钮的权限
           const hasPermission = checkPermission(binding.value);
           if (!hasPermission) {
               el.disabled = true;
           }
       }
   });

这里的 checkPermission 是一个假设的函数,用于检查权限。然后在组件中使用这个指令:

javascript 复制代码
   <template>
       <button @click="handleClick" v - permission - check="'button - click - permission'">
           Base Button
       </button>
   </template>
2.2、混入方式实现装饰功能

假设我们有一个基础的显示数据的 Vue 组件:

javascript 复制代码
   <template>
       <div>{{ data }}</div>
   </template>

   <script>
   export default {
       data() {
           return {
               data: 'Base Data'
           };
       }
   };
   </script>

我们可以创建一个混入(mixin)来装饰这个组件,例如给数据添加格式化功能的混入。定义混入:

javascript 复制代码
   const formatDataMixin = {
       computed: {
           formattedData() {
               return format(this.data);
           }
       }
   };

这里的 format 是一个假设的函数,用于格式化数据。然后在组件中使用这个混入:

javascript 复制代码
   export default {
       mixins: [formatDataMixin],
       data() {
           return {
               data: 'Base Data'
           };
       },
       computed: {
           // 可以在组件中继续使用原始数据或者新的格式化后的数据
           combinedData() {
               return this.data +'(' + this.formattedData + ')'
           }
       }
   };

三、装饰器模式的使用场景

1.用户界面增强

在前端界面开发中,常用于给用户界面组件添加额外功能。例如,给输入框组件添加验证功能,如必填项验证、格式验证等。可以创建一个 ValidationDecorator 来装饰输入框组件,在用户输入数据时进行验证,而不需要修改输入框组件的原始代码。

2.权限管理

对于一些页面元素,如菜单、按钮等,可以使用装饰器模式添加权限检查功能。例如,创建一个 PermissionDecorator,它在渲染组件之前检查用户是否具有访问该组件所代表功能的权限,如果没有权限则隐藏或禁用该组件。

3.数据处理与展示

在处理从服务器获取的数据时,可以使用装饰器模式对数据进行加工和美化后再展示。例如,创建一个 FormattingDecorator,如果获取到的是日期数据,可以将其格式化为更友好的显示形式,如将时间戳转换为指定格式的日期字符串。

四、装饰器模式的优点

1.灵活性

可以根据具体需求动态地组合装饰器,添加或移除功能。例如,在不同的用户角色或业务场景下,可以灵活地给组件添加不同的功能装饰,而不需要重新编写组件的核心代码。

2.遵循开闭原则

不需要修改原始类的代码就可以扩展其功能。这使得在项目维护和功能迭代过程中,代码的稳定性更高。当需要添加新功能时,只需创建新的装饰类并进行组合即可。

3.单一职责原则的体现

每个装饰类只负责一个特定的功能扩展,使得代码结构更加清晰,易于理解和维护。开发人员可以专注于每个功能的实现,降低了代码的复杂性。

五、装饰器模式的缺点

1.增加复杂性

如果过度使用装饰器模式,会导致代码结构变得复杂,尤其是在有多个装饰器层层嵌套的情况下。这可能会使代码的调试和理解变得困难,对于新加入项目的开发人员来说,需要花费更多的时间来理解装饰器之间的关系。

2.可能影响性能

在某些情况下,由于装饰器的层层嵌套,可能会导致额外的函数调用开销,从而影响性能。特别是在对性能要求较高的应用场景中,需要谨慎使用装饰器模式并进行性能优化。

六、装饰器模式的注意事项

1.接口的稳定性

装饰类和被装饰类所实现的接口(或遵循的协议)应该保持稳定。如果接口发生变化,可能会导致装饰器与被装饰对象之间的不兼容,从而需要修改大量的代码。

2.避免过度装饰

要谨慎使用装饰器模式,避免创建过多不必要的装饰器以及过度嵌套装饰器。在设计阶段就应该评估功能需求,尽量保持装饰器结构的简洁性,以减少复杂性和性能问题。

3.装饰器顺序

在组合多个装饰器时,装饰器的顺序可能会影响最终的结果。例如,一个先进行数据加密再进行数据压缩的装饰器顺序,与先进行数据压缩再进行数据加密的顺序,得到的结果可能是不同的。因此,在使用装饰器模式时,需要明确装饰器的顺序以及其对功能的影响。

关于装饰器模式的分享就到此结束了,如果对于其他设计模式有兴趣的话,可以点击右下角"专栏目录"查看更多设计模式

相关推荐
庸俗今天不摸鱼16 分钟前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
QTX1873017 分钟前
JavaScript 中的原型链与继承
开发语言·javascript·原型模式
黄毛火烧雪下23 分钟前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox34 分钟前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞36 分钟前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行37 分钟前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox
m0_5937581038 分钟前
firefox 136.0.4版本离线安装MarkDown插件
前端·firefox
掘金一周41 分钟前
金石焕新程 >> 瓜分万元现金大奖征文活动即将回归 | 掘金一周 4.3
前端·人工智能·后端
三翼鸟数字化技术团队1 小时前
Vue自定义指令最佳实践教程
前端·vue.js
Jasmin Tin Wei1 小时前
蓝桥杯 web 学海无涯(axios、ecahrts)版本二
前端·蓝桥杯