装饰者模式

举报
yd_221104950 发表于 2020/12/02 23:27:23 2020/12/02
【摘要】 在策略者模式中,我们知道扩展一个对象的办法就是在父类中加上相应的接口或抽象类作为“占位符”,然后配上通用的方法去使用这个接口或抽象类中的方法,具体实现则独立于父类的实现,在运行时,才赋予具体的类。策略者模式很好的解决了多态和继承问题。比较适用于设计初始阶段,当有些类的功能与性能方面已经很完善了。我们再用策略者模式去添加行为的话,有可能会触发一些性能方面的问题。 所以当...

在策略者模式中,我们知道扩展一个对象的办法就是在父类中加上相应的接口或抽象类作为“占位符”,然后配上通用的方法去使用这个接口或抽象类中的方法,具体实现则独立于父类的实现,在运行时,才赋予具体的类。策略者模式很好的解决了多态和继承问题。比较适用于设计初始阶段,当有些类的功能与性能方面已经很完善了。我们再用策略者模式去添加行为的话,有可能会触发一些性能方面的问题。

所以当一个类设计完成并在各方面都已成熟稳定后,对这样的类,我们应该禁止对其进行修改。但是我们应该允许对其进行扩展。这就有点奇怪了,扩展在某种程度上就是修改。但是别忘了,继承此类,在子类中添加新行为也是一种扩展啊。

但在某种情况下,会出现继承滥用问题,导致系统中的类数量暴增。举个例子:假设我们给买饮料的店开发一套下单系统,通过系统下单收钱。我们设计一个父类,父类中有一个计算钱的方法cost,和需要子类指定的饮品名,然后我们将饮品,如奶茶、柠檬茶等继承父类各写成一个类,还有很多的配料抹茶、珍珠、奶昔、奶泡等与相应饮品搭配后形成的饮料继承父类也各写成一个类。每个类中都有一个此类饮品的价格的获取方法cost(),那么下单后,只需要将各个饮品对象的cost()相加,即可。但是随着饮品和配料的数量的增加,系统中就会出现非常多的类。最后类的数量就会呈现爆炸式增加如:
在这里插入图片描述

如果只是用继承来解决我们这套系统中的类的关系的话,那真不是个什么好办法,类的数量会增加得很快。

有什么办法可以解决继承又不会使类出现“爆炸”的现象呢?难道说将所有的配料和饮品都写到父类中去,然后根据点的饮品调用不同的方法。这方法好像能解决问题,但是随后有新的饮品和配料要加入销售,那该怎么办呢?所以这样做以后,不利于后期维护和扩展,只会将这个类撑得越来越大。

像这种通过继承可能会引发类“爆炸”的有什么办法可以既不用修改类又可以扩展父类呢?有,那就是装饰者模式了。

装饰者类其中一个最重要的特点是它包含要装饰的类的实例。这样装饰者类才能拥有要装饰的类的实例的所有东西。另一个重要特点是装饰者类和被装饰的类继承同一个父类,因为只有这样才能实现里氏替换原则:里氏替换原则,主张使用“抽象(Abstraction)”和“多态(Polymorphism)”将设计中的静态结构改为动态结构,维持设计的封闭性。“抽象”是语言提供的功能。“多态”由继承语义实现。所以装饰者之间可以互相装饰。

装饰者模式定义

动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

装饰者模式的UML

在这里插入图片描述
1.装饰者和被装饰对象都有相同的超类型。
2.我们可以用一个或多个装饰者包装一个对象。
3.既然装饰者和被装饰对象有相同的超类型,所以在任何原始对象(被包装的)的场合,可以用装饰者的对象代替它。
4.装饰者可以在所委托被装饰者的行为的前与后加上自己的行为,达到特定的目的。
5.对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。
6.装饰者与被装饰者必须是一样的类型,也就是有共同的超类,这是相当关键的地方。利用继承达到“类型匹配”,而不是利用继承获得“行为”。
7.当我们将装饰者与组件(Component)组合时,就是在加入新的行为。所得的新行为,并不是继承自超类,而是由组合对象得来的。
8.继承Component类是为了有正确的类型,而不是为了继承它的行为。行为来自装饰者和基础组件,或与其他装饰者之间的组合关系。

9.装饰者该做的事就是增加行为到被包装对象上。

让我们用装饰者来实现我们的点饮系统

UML
在这里插入图片描述
附上GitHub代码

文章来源: blog.csdn.net,作者:WongKyunban,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_40763897/article/details/88356484

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。