经典问题:咖啡馆问题
咖啡有四种类型:HouseBlend (混合咖啡)、DarkRoast (烧烤咖啡)、Decaf ( 脱咖啡因咖啡)和espresso(浓咖啡)
调味品如:Steamed milk(清蒸调味奶)、Soy(大豆)、Mocha(当成巧克力吧)、Whipped milk(我也不知道是什么?就当细小鞭吧)
简单分析一下,我们需要解决的问题大致有如下:
- 更改咖啡、调味品价格
- 增添咖啡和调味品
- 咖啡和调味品的各种组合
我的想法
两个抽象类:
Beverage做为所有cafe的超类,维持一个condiment的容器来存放所加入咖啡的所有调料品,实现getPrice()方法,该方法返回condiment容器中所有调料品的价格和自身价格的总和。
condiment作为所有调味品的超类,存放各自调料品的价格并提供接口访问
这样在更改价格,增添咖啡和调味品的时候都非常简单,不需要做太多的更改,同时可以实现所有的组合。
装饰模式的做法
首先注意到其实Beverage和condiment所需要实现和提供的功能都非常相似,且对于容器的维护效率很低下。
首先实现饮料Beverage超类:
public abstract class Beverage{ String description = "Unknow Beverage"; public String getDescription(){ return description; } public abstract double cost();}
然后让condimentDecorator调料品装饰类继承自Beverage类
public abstract class condimentDecorator extends Beverage{ public abstract String getDescription();}
接着去实现各个具体的类,HouseBlend (混合咖啡)、DarkRoast (烧烤咖啡)、Decaf ( 脱咖啡因咖啡)和espresso(浓咖啡)继承自Beverage类
Steamed milk(清蒸调味奶)、Soy(大豆)、Mocha(巧克力)、Whipped milk(细小鞭)继承自condimentDecorator类
对于调味品装饰的具体实现我们需要注意,内部需要维持一个Beverage类的对象,也就是我们需要装饰的对象
public class Mocha extends CondimentDecorator{ Beverage beverage; public Mocha (Beverage beverage){ this.beverage = beverage; } public String getDescription(){ return beverage.getDescription() + ",Mocha"; } public double cost(){ return 20+beverage.cost(); }}
接着是如何使用各种调味品装饰类去装饰咖啡
Beverage beverage = new Espresso();beverage = new Mocha(beverage );beverage = new Soy(beverage );
注意,通过在调味品装饰类中添加了这一个Beverage对象,且调味品装饰类也是继承自Beverage类,我们在装饰的时候可以实现多层的装饰。
装饰模式完美解决上述问题。