一杯cafe问题
假设我们需要设计一个cafe订单系统,用户可以选择coffee类型以及需要添加的小料,然后计算出它的价格,那么最朴素的方法就是创建一个coffee基类,然后不同类型的coffee继承自这个基类,然后计算他的价格,类图可以如下所示:
但是这样也是有个问题的,这会导致类爆炸(因为添加每一种小料就需要添加一个新的类),如下所示:
面对上面的问题,一种解决方法就是,我们可以在基类中增加小料的成员,那么就不会导致类型爆炸了,如下所示:
但是如果当我们增加了新的小料的时候呢?我们需要对基类进行修改,这实际上就破坏了我们的设计原则
第四个设计原则
类应该对扩展开放,对修改关闭
为了解决上面的问题,我们引入装饰者模式
装饰者模式
动态的将责任附加到对象上,若要扩展功能,装饰者提供了比继承更加有弹性的替代方案。
对应到上面的问题,我们可以首先创建一个cafe子类的对象,然后用奶泡装饰它,然后用糖装饰它,最终再计算其价格。
类图如下所示:
代码实现
首先创建一个Beverage基类1
2
3
4
5
6
7
8
9public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
然后创建一个小料的类,这个类要继承自Beverage类
1 | public abstract class CondimentDecorator extends Beverage{ |
然后我们创建我们的coffee类型
1 | public class Espresso extends Beverage { |
1 | public class HouseBlend extends Beverage { |
然后创建我们的小料的装饰类
1 | public class Mocha extends CondimentDecorator { |
1 | public class Whip extends CondimentDecorator { |
最后的测试代码如下:
1 | public class CoffeeDemo { |
从上面的代码可以看出,我们创建了coffee对象,然后将其传给各个装饰类,这样就起到了装饰的作用。
装饰者模式的一个缺点
如果要吐槽装饰者模式的话,那么一个点就是这个模式的类太多了(而且都是小的类)就比如我们的coffeeDemo,每一种配料,每一个size都要一个类,确实有点多而杂,但是比最初的方案还是好太多了。
代码归档
https://github.com/changyuanchn/DesignPattern/tree/main/src/com/changyuan/decoratorPattern