此时,我不想在打电话之前听到彩铃了,很简单:我们不装饰它就好了!
此时,我想在打电话前报告一下时间,在打完电话之后听彩铃。
- 注意:虽然说要改动类中的代码,但是这种改动是合理的。因为我定义出的
GiveCurrentTimePhone类
和MusicPhone类
本身从语义上就没有规定扩展功能的执行顺序 - 而继承不一样:先继承Phone->实现MusicPhone->再继承MusicPhone实现GiveCurrentTimePhone。这是固定的,从继承的逻辑上已经写死了具体的代码,是难以改变的。
所以我们还是可以很简单地完成功能:
二、装饰模式讲解
可能有的同学在看完上面的代码之后,还是迷迷糊糊地不知道装饰模式是怎么实现“装饰”的。下面我就再来解析一下:
- 第一步:我们有一个Phone接口,该接口定义了Phone的功能
- 第二步:我们有一个最简单的实现类iPhoneX
- 第三步:写一个装饰器抽象类PhoneDecorate,以组合(构造函数传递)的方式接收我们最简单的实现类iPhoneX。其实装饰器抽象类的作用就是代理(核心的功能还是由最简单的实现类iPhoneX来做,只不过在扩展的时候可以添加一些没有的功能而已)。
- 第四步:想要扩展什么功能,就继承PhoneDecorate装饰器抽象类,将想要增强的对象(最简单的实现类iPhoneX或者已经被增强过的对象)传进去,完成我们的扩展!
再来看看下面的图,就懂了!
往往我们的代码可以省略起来,成了这个样子(是不是和IO的非常像!)
// 先增强听音乐的功能,再增强通知时间的功能 Phone phone = new GiveCurrentTimePhone(new MusicPhone(new IphoneX()));
结果是一样的:
2.1装饰模式的优缺点
优点:
- 装饰类和被装饰类是可以独立的,低耦合的。互相都不用知道对方的存在
- 装饰模式是继承的一种替代方案,无论包装多少层,返回的对象都是is-a的关系(上面的例子:包装完还是Phone类型)。
- 实现动态扩展,只要继承了装饰器就可以动态扩展想要的功能了。
缺点:
- 多层装饰是比较复杂的,提高了系统的复杂度。不利于我们调试~
三、总结
最后来补充一下包装模式和代理模式的类图:
对象增强的三种方式:
- 继承
- 包装模式
- 代理模式
那么只要遇到Java提供给我们的API不够用,我们增强一下就行了。在写代码时,某个类被写死了,功能不够用,增强一下就可以了!
理解包装模式,接下来就开始IO之旅咯~~~
参考资料: