设计模式之-装饰器模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之-装饰器模式相关的知识,希望对你有一定的参考价值。

参考技术A 圣诞节快到了,很多小伙伴都会装饰圣诞树,我们会往树上挂上很多有节日气氛的装饰品,但我们并不会破坏这棵树原有的结构,这便是我们生活中的装饰器模式。

JavaScrip t中装饰器模式的一个很好地表现便是 装饰函数 。比如我们在维护一个项目的时候,突然来了新的需求,需要我们往原来的函数中添加新的功能。原来的函数是以前的同事写的又经过好几个人的手,里面的实现非常杂乱,最好的方法是尽量不去改动原函数,通过保存原引用的方式去改写这个函数。

比如我们想给 window 绑定 onload 事件,但是如果这个事件之前有人绑定过,我们直接写就会覆盖掉之前事件中的行为。为了避免覆盖掉之前的 window.onload 函数中的行为,我们一般都会先保存好原先的 window.onload ,把它放入新的 window.onload 里执行

新的 window.onload 函数就是我们的装饰函数。

上面这种方式存在以下两个问题:

为了解决这两个问题,我们用 高阶函数 来装饰函数。

我们在原来的函数上添加新行为,添加的新行为要么先于函数执行,要么后于函数执行。我们实现两个方法—— Function.prototype.before 给函数添加先于函数执行的新行为, Function.prototype.after 给函数添加后于函数执行的新行为:

再回到上面 window.onload 的例子,我们可以这样写:

假如我们给搜索按钮添加埋点事件,需要做两件事,一是实现搜索功能,另一个是上报数据。

在第二种实现方式(装饰器模式实现)中,我们对按钮职责进行了更细的划分,保证了函数单一职责原则。

下面是一个我们封装的 axios 请求

现在需要给每个请求都加上 token 参数

在装饰器模式实现方式中我们没有改变原函数,原函数是一个比较纯净的单一职责函数,提高了request函数的可复用性。

设计模式之装饰器模式

装饰器模式,顾名思义,就是将某个类重新装扮一下,使得它比原来的功能更加强大,这就是装饰器所要达到的目的。但是作为原来这个类的使用者,不应感受到装饰前和装饰后有什么不同,否则就破坏了原有类的结构了,所以装饰器模式要做到对被装饰类的使用者透明,这是对装饰器模式最基本的要求。

装饰器模式的结构

下图是一个装饰器模式的典型的类图结构,各个角色的描述如下:

  • Component:抽象组件角色,定义一组抽象的接口,规定被装饰组件有哪些功能
  • ConcreteComponent:实现这个抽象组件的所有功能
  • Decorator:装饰器角色,它持有Component角色的引用,定义一个和抽象组件一致的接口-
  • ConcreteDecorator:装饰器的具体实现,负责实现装饰器角色定义的功能

Java IO中的装饰器模式

装饰器模式的作用就是赋予被装饰器的类更多的功能,在Java IO类库中,有很多不同的功能组合情况,这些不同的功能组合就是使用装饰器模式实现的,下面以FilterInputStream为例来说明。

InputStream类就是以抽象组件的角色存在的,而FileInputStream就是具体实现抽象组件所有功能的组件,FilterInputStream是装饰器角色,他实现了InputStream的所有接口,并且持有InputStream对象的引用,BufferedInputStream就是具体装饰器的实现者,它给InputStream添加了附加功能,使得InputStream读取的数据放在内存中,提升读取效率。

装饰器模式和适配器模式的区别

装饰器模式和适配器模式都有一个别名就是包装模式(wrapper),它们都起到了包装一个类或则对象的作用,但是它们的使用目的不同,装饰器模式不改变被包装的接口,仅仅是争强原来接口的功能,而适配器模式要将一个接口转变为另一个接口,目的是通过改变接口达到重复使用。

以上是关于设计模式之-装饰器模式的主要内容,如果未能解决你的问题,请参考以下文章

java设计模式之装饰器模式

Java设计模式之——装饰器模式

设计模式之装饰器模式

二十三种设计模式之装饰器模式

设计模式之门面模式与装饰器模式详解和应用

设计模式之装饰器模式