《深入浅出设计模式》 笔记第三章 装饰者模式
有这么一个需求:咖啡厅做饮料。饮料分基础饮料(浓缩咖啡、普通咖啡等等)和调味饮料(果汁、豆浆等)。现要求建立一个系统,计算饮料的价格和饮料的描述,成品饮料会在基础饮料的上搭配调味饮料。
第一次尝试
很明显,这种实现很烂。
第二次尝试
该次尝试将调味饮料放在了超类的属性(布尔值)中,每加入一种调味饮料,就需要添加一个属性和Get、Set方法。
但这种尝试违反了开放-关闭原则。
开放-关闭原则
设计原则:类应该对扩展开放,对修改关闭。
在选择需要被扩展的代码部分时要小心。每个地方都采用开放-关闭原则,是一种浪费,也没有必要,还会导致代码变得复杂且难以理解。
装饰者模式
装饰者模式下的系统,层层装饰:
装饰者模式:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
装饰者模式的特点:
- 装饰者和被装饰者对象有相同的超类型
- 可以用一个或多个装饰者包装一个对象
- 既然装饰者和被装饰者对象有相同的超类型,所以在任何需要原始对象(被包装的)的场合,可以用装饰过的对象替代它
- 装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的
- 对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用需要地装饰者来装饰对象
装饰者模式的类图:
##装饰者模式下的系统
类图:
代码实现
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
public class Espresso extends Beverage {
public Espresso() {
description = "Espresso";
}
public double cost() {
return 1.99;
}
}
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "House Blend Coffee";
}
public double cost() {
return .89;
}
}
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();
}
}
public class Test {
public static void main(String[] args) {
Beverage beverage = new Espresso();
System.out.println(beverage.description + " $" + beverage.cost());
Beverage beverage2 = new HouseBlend();//被装饰
beverage2 = new Mocha(beverage2);//装饰者
}
}
真实世界的装饰者:Java I/O
装饰者模式的“缺点”:
- 利用装饰者模式,常常造成设计中有大量的小类,数量很多,可能会造成使用此API程序员的困扰
- 类型问题:有些代码会依赖特定的类型,却没有考虑周全
- 采用装饰者在实例化组件时,将增加代码的复杂度