设计模式之装饰者模式

前言

在面向对象的世界里,要想对一个类增加新的行为,可以通过继承的方式轻松实现。但是如果过多的使用这种方式,很容出现类爆炸,这时如果在父类中修改一个行为会影响到所有的子类,所产生的风险也无法估量,要想在这样子的代码结构中扩展内容,简直会原地爆炸。那么如何才能优雅的实现既能给类增加新的行为,又不会创建过多的子类呢?今天我们介绍一个能够给爱用继承的人一个全新的设计眼界的设计模式----装饰者模式

装饰者模式

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

虽然说明了装饰者模式的核心内容,有了一个抽象的概念,但是并没有说明我们要怎么在实际实现中如何应用它。我们来看看装饰者模式的类图,加深对装饰者模式的理解。

结构

这里废话不多说,老规矩直接上类图:
在这里插入图片描述

实战

结合个例子来看看怎么使用装饰者模式。例如,假定要实现一个计算咖啡店里各种咖啡的价格的软件,咖啡由各种的配料制作而成,分别为:DarkRoast(深培咖啡):6元,Milk(牛奶):2元,soy(豆浆):1元,Mocha(摩卡):4元等,可以根据需要添加各种原料。
那么如何实现这个软件呢?结合上面的类图:
在这里插入图片描述
DarkRoast是一种咖啡作为一个具体组件,Milk、Soy、Mocha是一种配料作为装饰者使用。通过这四种组件不同的组合,可以制作出不同口味的咖啡。例如:一个标准杯加奶加豆浆深焙咖啡:Mik+Soy+DarkRoast = 9元。如下图所示:
在这里插入图片描述
使用装饰者模式只要继承(实现)Beverage就可新增咖啡原料,通过继承(实现)Decorator类新增各种配料装饰者,而且能够根据顾客需要轻松的进行组合,无需修改代码,亦可实现计算所有卖出咖啡的价格。

从模式中窥探设计原则

设计原则:对扩展开放,对修改关闭。

该原则的目标是允许对类进行扩展,在不修改原有代码的情况下,就可以搭配出新的行为。在本模式中对于基础组件如果想增加新的行为,可以使用装饰者来包装扩展,且对调用者是无感知的,无需修改原有的代码。

使用场景

  • 在不影响其他使用场景的情况下,以动态,透明的方式扩展行为。
  • 在类的定义里不允许采用生成子类的方式进行扩展行为时。一种情况是,有大量独立的扩展,为了避免随机组合产生大量的子类。另外一种情况是,某个类被定义为final不允许继承。
  • 用于类的某些行为可动态配置,无需固定写死在类中。

优缺点

优点:
  • 比静态继承更加灵活:通过动态组合的方式来扩展,在运行时可动态的增加或者删除,甚至可以增加重复的行为。类行为的扩展比静态继承更加的灵活,成本更低。
  • 避免在层次结构高的类中有太多的特征: 可以将层次结构高的类中相对独立的行为独立成一个个装饰者,将原本复杂的类简单化。后续通过按需组合来增加行为,来使功能简单的类变成功能复杂的。
缺点:
  • 会有很多的装饰者小对象: 这些类大部分都是相同的,只在一小部分特征行为里有所不同。对于了解这个系统的人比较容易定制,但对于不了解的人就相对很难学习,debug也比较困难。
  • Decorator与Component两者不一样: 被装饰过的组件与装饰组件虽然都是统一父类对调用者来说包装过程是透明的,但是从对象的角度来看他们之间是完全不同的两个对象。因此,使用装饰者一定要注意对象的改变,不应该依赖对象标识。
总结

装饰者模式为我们提供了一个比继承更加灵活的扩展行为的方式。是一种利用组合和委托的来代替继承的弹性设计方案。装饰者可以在组合的过程中调整被装饰组件的行为,甚至是完全改变。但是也是一把双刃剑,使用的过程中不能单单只考虑其带来的优势,也要注意其所带来的各种小对象,不易调试,以及对象改变的问题。在实际使用中不可过多的使用,将优点和缺点充分考虑景区,尽量使用简单的方案。

参考文献

《Head First 设计模式》
《设计模式-可复用面向对象软件的基础》

个人公众号:基石分享社

欢迎关注我的公众号,该公众号会持续输出Android开发过程中的各种基础知识的文章,共同学习成长。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值