什么是“装饰者模式”
装饰者模式:装饰者模式可以动态地将责任附加到对象上。若要拓展功能,装饰者模式提供了比继承更有弹性的替代方案。
在面向对象设计过程中,我们可以遵循一个原则:开闭原则(对拓展开放,对修改关闭)
而装饰者模式就很好的遵循了这个原则,在对类进行拓展的时候可以不修改代码,以便搭配新的行为。这种设计更具有弹性,可以更好地应对改变和接收新的需求。
为什么要用“装饰者模式”
我们举个简单的例子:
我们需要设计一个咖啡订单系统,我们很容易就可以想到,新建一个抽象类Beverage,
1 | /** |
然后通过子类继承Beverage并实现抽象方法cost(),得到不同的价格。
那么问题来了: 如果我要在咖啡中添加各种调料,例如:蒸奶、豆浆、摩卡、奶泡等等。 添加不同的调料收取的价格不同,我们该怎么办?有些人会想到,根据不同的搭配组合实现不同的类,那么这个想法会发生什么事情呢?没错。。。类爆炸!
如何使用装饰者模式
那么这个时候,装饰者模式就可以上场了:
我们首先来看看装饰者模式的类图
组成
- Component 抽象构件 :一个抽象类或者一个接口
- ComcreateComponent 具体构件:抽象类或者接口的实现,我们要装饰的就是它(咖啡)
- Decorator 装饰角色: 一个抽象类或者一个接口,里面必然有一个指向Component 抽象构件的属性
- 具体装饰角色:装饰用的具体角色,实现或继承了Decorator 装饰角色
实现
了解了具体的组成角色,那么我们就可以实现一下了
首先,根据类图我们需要准备一个Component 抽象构件,其实我们在文章开始就已经准备好了:
1 | /** |
接下来,我们准备一个ComcreateComponent 具体构件,也就是需要被我们装饰的对象(这里是咖啡)
1 | /** |
然后,我们准备一个Decorator 装饰角色,
1 | ** |
最后,我们实现一个这个Decorator 装饰角色抽象类,使它变成具体的装饰角色
1 | public class Mocha extends CondimentDecorator { |
完成之后,我们测试一下被我们装饰后的咖啡长什么样:
1 | public class StarbuzzCoffee { |
输出结果:
1 | 浓缩咖啡, 摩卡, 奶泡 ¥21.8 |
从输出结果看,我们确实根据调料改变了浓缩咖啡的价格,所以这就是装饰者模式的好处。
那么,总结来了
优点:
- 装饰类和被装饰类可以独立发展,不会互相耦合。
- 装饰者模式是继承的一个替代方案。我们不管装饰多少层,最终返回的还是该对象。
- 装饰者模式可以动态拓展一个实现类的功能。
缺点:
- 装饰层数过多的话,会导致调试困难,系统复杂度提高。
应用场景:
- 需要动态地拓展某个类的功能或者添加一个附加功能。
- 需要为一批兄弟类添加功能或者改装,首选装饰者模式。
感谢阅读本博客。
欢迎关注我的博客:https://li-weijian.github.io/
欢迎关注我的CSDN:https://blog.csdn.net/qq352642663
需要联系请加QQ:352642663
欢迎联系我共同交流