装饰者模式
引入示例
接下来,先假设一个场景:蜜雪冰城有以下几种原味饮品
种类 | 价格 |
---|---|
原味奶茶(Milk Tea) | 10 |
原味咖啡(Coffee) | 15 |
原味果茶(Nectar) | 8 |
饮品还有量的系数如
杯量 | 价格倍数 |
---|---|
小杯 | x1 |
中杯 | x1.5 |
大杯 | x2 |
并且,为了满足客户的多种需求,蜜雪冰城还有以下的集中配料价位表
配料种类 | 价格 |
---|---|
糖(Sugar) | 1 |
豆浆(Soy) | 1 |
巧克力(Chocolate ) | 3 |
为了节省人员计算客户买饮品加配料的时间成本,现需要你设计一个系统(),如果一个客户买了大杯的果茶,并添加了豆浆和糖两种调料,那么店员只需要向系统中选择原始饮品,选择杯量,选择配料,选择完成后,系统即可计算出客户订单的价格。需要注意,在未来,蜜雪冰城随时可能增加新饮品、杯量、配料
对于上面的示例,相信没有人会为每种可能的组合去设计一个类,比如:加糖的小杯果茶。这样的话系统中类的数量将会是一个指数级的增长。
接下来是一个我去思考这个系统时提出的一个类图:
刚相出这个类图时,觉的已经很能降低系统类图间的耦合度了,只需要去实现上面的三个抽象类,然后客户下订单的过程也就是实例化Drink Price类的过程,只需要顶一个计算价格的算法即可得出总价格。
但:①:当蜜雪冰城需要新增一个维度的价格,比如:加热+5元,冰镇+5元,那么久需要新增一个接口/抽象类,最重要的是——Drink Price类中的需要新增一个属性,calculate方法也需要重新设计。②当蜜雪冰城做活动,新增了一个Size——超大杯,并且这个超大杯价格并不按倍数计算,而是直接+10元,那么calculate方法还是需要变化…(如果你发现了其他问题,欢迎致信斧正)
模式引入
接下来就是该引入装饰者模式了
定义
装饰者模式动态地将责任附加到对象上,若要扩展功能,装饰者模式提供了比继承更具有弹性的替代方案
类图
问题代入
在对于上面的问题,个人认为下面的图可以很形象地表示装饰者模式的作用原理
在对装饰者模式有所了了解之后,就可以将装饰者模式应用到最开始的示例之中了
如上图,定义了三个具体的需要被装饰的类,并且定义了两个维度的增值服务
根据以上的类图,就可以写出示例代码了,接下来是我提供的运行截图,代码请到装饰者模式代码
Java中的装饰者模式
总结
新设计原则:
对扩展开放,对修改封闭
当编写装饰者时,不应该去依赖于某种具体的被装饰类。