装饰者模式动态地将额外责任附加到对象上。对于拓展功能,装饰者提供子类化的弹性替代方案。 --《Head First Design Patterns》中的定义
根据上述定义,简单来说,装饰者模式就是对原有的类,增加一些额外的功能或者行为。用普通的继承或者组合也可以实现,但是单纯用继承或者组合来做,会产生大量的拓展类而导致"类爆炸"。
书中用咖啡的价格为例,说明了类爆炸这个概念:
咖啡店的咖啡的种类有4种,每种的价格不一样
若除了咖啡本身,还可以要求加上不同的调料,例如蒸奶(milk)、豆奶(soy)、摩卡(Mocha)。这样子,子类的拓展组合,就会有很多种,从而导致类爆炸,如下图所示。
以上述咖啡店的咖啡价格为例子
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
2. 咖啡种类的拓展类: 对应上图中的ConcreteComponent
public class Espresso extends Beverage{
public Espresso() {
description = "Espresso";
}
@Override
public double cost() {
return 1.99;
}
}
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "HouseBlend";
}
@Override
public double cost() {
return .89;
}
}
3. 调料类
public class Mocha extends CondimentDecorator {
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
@Override
public double cost() {
return beverage.cost() + .20;
}
}
public class Whip extends CondimentDecorator{
public Whip(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", whip";
}
@Override
public double cost() {
return beverage.cost() + .10;
}
}
4. 测试
public static void main(String[] args) {
// 要一杯浓缩咖啡,不加调料
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.cost());
//要一杯HouseLand,带有2份mocha和whip
Beverage beverage1 = new HouseBlend();
beverage1 = new Mocha(beverage1);
beverage1 = new Mocha(beverage1);
beverage1 = new Whip(beverage1);
System.out.println(beverage1.getDescription() + " $" + beverage1.cost());
}
上述的咖啡喝调料可以在不改动基类代码的基础上,进行随意组合。
类应该对拓展开放,对修改关闭(开闭原则)
java中的I/O流
参考:装饰者模式