美文网首页
掌握设计模式之装饰者模式

掌握设计模式之装饰者模式

作者: 闻人的技术博客 | 来源:发表于2019-07-24 22:37 被阅读0次

前言

当应用开发中,我们要为一个对象在原有功能上进行扩展增强时,往往采用继承的方式,而继承过多时就会使得功能类更加复杂,不利于维护,而设计模式中装饰者模式可以帮助我们更好对应这种场景,装饰者模式可以做到让对象能够动态地进行功能扩展,而不影响其他对象. 那究竟它是如何实现的呢,又如何实际应用呢,就让我们一起来学习下这个模式吧。

模式定义

装饰者模式属于结构型设计模式,首先我们先了解下装饰者模式的定义。

In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern.

简而言之, 装饰者模式就是动态地为一个对象扩展额外的功能,无论是动态还是静态,都不影响相同类的其他对象的行为, 这样使得对象在运行时更加灵活。

装饰者实现的方式通常为组合或者继承,可以让客户端根据需求进行对应的装饰,来达到功能增加的目标。为了简化理解,装饰者模式中装饰一词其实就是给原来的对象添加额外功能。

模式结构

接下来我们看下装饰者模式的层次结构和主要角色.

  • Component 抽象组件,最原始,核心的对象,通常为接口或者抽象类.
  • ConcreteComponent 具体组件,对 Component 的实现,也是需要装饰的对象.
  • Decorator 装饰者, 通常为抽象组件的抽象实现, 它的属性一定有私有变量指向 Component.
  • ConcreteDecorator 具体装饰对象,是 Decorator 的具体实现, 用于将原始,核心的方法装饰增强的类.

从图中看到,接口 Component 会有对应的实现类 ConcerateComponent,要对具体实现类进行功能增强,就需要对应的具体装饰者 ConcreteDecorator ,它通过内部引用 Component 类型的 ConcerateComponent 对象 ,在接口方法的默认实现上,允许添加额外的逻辑和功能代码。

模式实现

现在我们用喝咖啡的例子来实现下装饰者模式,假设我们要买一杯咖啡,需要加糖,加奶,而什么都不加的咖啡与加奶,加糖的价格都不一样,我们就要计算调制一杯加糖加奶的咖啡需要花费多少钱。

这里咖啡就是我们的具体组件 ConcerateComponent, 奶和糖就是具体装饰对象 ConcreteDecorator。 为了简单,我们先创建一个Component接口类 Drink, 定义两个方法用来获得价格和描述:

接着,创建一个 ConcreteComponentCoffee 实现 Drink 接口.

现在就需要一个抽象类 DrinkDecorator,用于扩展实现功能增强.

然后就是实现具体装饰对象 MilkSugar.

最后客户端实现制作咖啡的动作:


下图为示例的类图:

可以从上面例子看出,通过添加不同的材料,价格不同,并且描述信息也不一样,并且添加顺序可以动态改变,甚至不添加,让对象变得十分灵活, 这就是装饰者模式的精髓所在。

模式使用场景

装饰者模式同样大量应用在 JDK 源码中,我们经常可以看到:

装饰者模式可以让程序中对象在运行时中进行功能的增强和移除,并且采用更灵活的组合方式来进行扩展。

模式的得与失

优点:

  • 在不影响其他对象的情况下,动态为单个对象新增功能。
  • 装饰类与被装饰类 (ConcreteComponent) 相互独立,互不耦合,易于扩展。
  • 代替继承方式的功能实现,减少继承类的存在。

缺点:

  • 装饰层次过多时会让被装饰的对象更复杂,不容易理解,比如使用 Java I/O 的 DataInputStream 对象读取数据为 Java 基本类型值时会这样使用:

    DataInputStream is = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
    
  • 程序中若有太多的装饰类,理解和使用上略有难度。

结语

掌握装饰者模式的精髓在于通过一层层的包装,让原来对象的功能更加强大,且包装过程是动态的,灵活可以移除的,到最后还是会调用到原对象最原始的功能。

参考

推荐阅读

相关文章

  • java IO 的知识总结

    装饰者模式 因为java的IO是基于装饰者模式设计的,所以要了解掌握IO 必须要先清楚什么事装饰者模式(装饰者模式...

  • 掌握设计模式之装饰者模式

    前言 当应用开发中,我们要为一个对象在原有功能上进行扩展增强时,往往采用继承的方式,而继承过多时就会使得功能类更加...

  • JavaScript 设计模式核⼼原理与应⽤实践 之 结构型设计

    JavaScript 设计模式核⼼原理与应⽤实践 之 结构型设计模式 装饰器模式,又名装饰者模式。它的定义是“在不...

  • Java设计模式之 —— 装饰者(Decorator) — 点

    Java设计模式之 —— 装饰者(Decorator) — 点炒饭 下面会用做炒饭的例子来描述一下装饰者设计模式,...

  • 设计模式

    设计模式 单例模式、装饰者模式、

  • 设计模式笔记汇总

    目录 设计原则 “依赖倒置”原则 未完待续... 设计模式 设计模式——策略模式 设计模式——装饰者模式 设计模式...

  • 设计模式

    常用的设计模式有,单例设计模式、观察者设计模式、工厂设计模式、装饰设计模式、代理设计模式,模板设计模式等等。 单例...

  • 设计模式之装饰者模式

    如果你没了解过装饰者模式,那么请继续往下看,如果你是老司机,那么,你可以快速往下看。 开始装个13,再进入正文。 ...

  • 设计模式之装饰者模式

    该模式可以避免滥用继承,在使用对象组合的方式,就能做到在运行时装饰类,此后便能在不修改任何底层代码的情况下给对象赋...

  • 设计模式之装饰者模式

    装饰者模式的定义是动态地给一个对象添加一些额外的职责。就增加功能来说,装饰者模式比生成子类更加灵活。 通常给一个对...

网友评论

      本文标题:掌握设计模式之装饰者模式

      本文链接:https://www.haomeiwen.com/subject/qpdqrctx.html