装饰者模式(Decorator Pattern)
装饰者模式——动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
原则
类应该对扩展开放,对修改关闭。
类图
Code
// Beverage相当于抽象的Component类
public abstract class Beverage{
// 由每个子类设置,用来描述饮料
String description ="Unknow Beverage";
public String getDescription(){
return description;
}
// cost()必须在子类实现
public abstract double cost();
}
// 让Espresso扩展自Beverage类,因为Espresso是一种饮料(浓缩咖啡)
public class Espresso extends Beverage{
public Espresso(){
// 饮料的描述。description实例变量继承自Beverage
description ="Espresso";
}
// 浓缩咖啡的价格
@Override
public double cost(){
return10.0;
}
}
// 另一种饮料
public class HouseBlend extends Beverage {
public HouseBlend(){
description ="HouseBlend";
}
@Override
public double cost() {
return10.0;
}
}
// 必须让CondimentDecorator能取代Beverage,所以将CondimentDecorator扩展自Beverage类
public abstract class CondimentDecorator extends Beverage{
// 所有的调料装饰者都必须重新实现getDescription()方法
public abstract String getDescription();
}
// 摩卡是一个装饰者,所以让它扩展自CondimentDecorator
public class Mocha extends CondimentDecorator{
// 要让Mocha能够引用一个Beverage,做法如下:
// 1.用一个实例变量记录饮料,也就是被装饰者
// 2.想办法让被装饰者(饮料)被记录到实例变量中。
// 这里的做法是:把饮料当作构造器的参数,
// 再由构造器将此饮料记录在实例变量中
Beverage beverage;
public Mocha(Beverage beverage){
this.beverage = beverage;
}
// 我们希望叙述不只是描述饮料(例如“DarkRoast”),
// 而是完整地连调料都描述出来(例如“DarkRoast, Mocha”)。
// 所以首先利用委托的做法,得到一个叙述,然后在其后加上附加的叙述(例如“Mocha”)
public String getDescription(){
return beverage.getDescription() + ", Mocha";
}
@Override
public double cost(){
return 3.5+ beverage.cost();
}
}
// 测试代码:
// 订一杯Espresso,不需要调料,打印出它的描述与价钱
Beverage beverage =new Espresso();
System.out.println(beverage.getDescription()+" $"+ beverage.cost());
// 制造出一个DarkRoast对象
Beverage beverage2 =new DarkRoast();
// 用Mocha装饰它
beverage2 =new Mocha(beverage2);
// 用第二个Mocha装饰它
beverage2 =new Mocha(beverage2);
// 用Milk装饰它
beverage2 =new Milk(beverage2);
System.out.println(beverage2.getDescription()+" $"+ beverage2.cost());
Reference
http://cashow.github.io/head-first-design-patterns-notes-decorator-pattern.html