一.案例引入
1.案例描述
星巴克咖啡订单项目(咖啡馆)
①咖啡种类/单品咖啡:Espresso、ShortBlack、LongBlack、Decaf
②调料:Milk、Soy、Chocolate
③要求在扩展新的咖啡种类时,具有良好的扩展性、改动方便、维护方便
④使用OO(面向对象)的思维来计算不同种类咖啡的费用:客户可以点单品咖啡,也可以单品咖啡+调料组合
2.较差的方案一
方案描述
方案一缺点
这样设计,会有很多类,当我们增加一个单品咖啡,或者一个新的调料时,类的数量就会倍增,出现类爆炸。
3.还行的方案二
方案描述
前面分析到方案1因为咖啡单品+调料组合会造成类的倍增,因此可以做改进,将调料内置到Drink类,这样就不会造成类数量过多,从而提高项目的维护性
说明:milk,soy,chocolate可以设计为Boolean,表示是否要添加相应的调料。考虑到用户可以添加多份调料,可以将hasMilk的返回值设置成int类型。
方案评价
所以就引出了装饰者模式
二.装饰者模式
1.定义
动态地将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)
2.装饰者模式原理图
3.装饰者模式原理描述
描述
Component就是将主体和装饰者抽象出来的一个抽象类
4.装饰者模式解决上述问题的UML类图
Coffee是缓冲层。
关于设计方案的四点说明
订单示例(2份巧克力+1份牛奶的LongBlack)
订单说明
5.具体代码
Drink
public abstract class Drink {
public String des;//描述
private float price = 0.0f;
/**
* 计算费用的抽象方法,由子类来实现
* @return
*/
public abstract float cost();
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
Coffee
public class Coffee extends Drink{
@Override
public float cost() {
return super.getPrice();
}
}
Espresso
public class Espresso extends Coffee {
public Espresso(){
setDes("意大利咖啡");
setPrice(6.0f);
}
}
Decorator
public class Decorator extends Drink{
private Drink obj;
public Decorator(Drink obj){
this.obj = obj;
}
@Override
public float cost() {
//getPrice()是自己的价格
return super.getPrice() + obj.cost();
}
@Override
public String getDes() {
//obj.getDes()输出被装饰者的信息
return des + " " + getPrice() + " && " + obj.getDes();
}
}
Chocolate
public class Chocolate extends Decorator{
public Chocolate(Drink obj) {
super(obj);
setDes("巧克力");
setPrice(3.0f);
}
}
Milk
public class Milk extends Decorator{
public Milk(Drink obj) {
super(obj);
setDes("牛奶");
setPrice(1.5f);
}
}
CoffeeBar
public class CoffeeBar {
public static void main(String[] args) {
//2份巧克力+1份牛奶的Espresso
Drink order = new Espresso();
//加入1份牛奶
order = new Milk(order);
order = new Chocolate(order);
order = new Chocolate(order);
System.out.println(order.getDes());
System.out.println(order.cost());
/**
* 巧克力 3.0 && 巧克力 3.0 && 牛奶 1.5 && 意大利咖啡
* 13.5
*/
}
}