装饰者模式定义
装饰者模式动态地将额外的责任附加到对象上。对于扩展功能,装饰者提供子类之外的弹性替代方案。
装饰者类图
装饰者模式理解
1.咖啡店卖咖啡的例子
首先我们有个咖啡店,这个咖啡店卖咖啡,并且咖啡也可以进行加料。
如果我们的设计考虑,只要有一种加料的可能就设计一个类,就会造成类的爆炸。如黑咖啡可以加牛奶,也可以加泡泡,那么我们就可能有不同的两个类,黑咖啡泡泡类,黑咖啡牛奶类,很明显,这样设计是不行的。
如果我们考虑,把一切的加料需求都放入所有咖啡的基类,那么其它有咖啡如果要加料就从基类中去拿,但是这样每当有新的加料时,又回造成要对基类的修改,并且有些咖啡类也不需要这些加料。
所以,综上所述,我们可以考虑用装饰者模式,既然加料那么麻烦,我们就考虑得简单一点。
对于不管是咖啡,还是加料,他们对应的类,都是一个基类的子孙类,他们可以作为各自的成员,那么如果点了一杯黑咖啡,又要加料泡泡,那就把黑咖啡传递给泡泡,如果再要加牛奶,那就把泡泡类对象再传递给牛奶,此时就形成一种包装的现象。类似于下图。
那么如果我要计算整个花销,则一层层调用,最后会给出总花销。
2.Java IO类中设计的实际例子
既然我要扩展功能,又不要修改其代码或者利用它重新写一个类,那我就拿到他的类,那么就具有了其功能,并利用其功能进行封装,那么这就是装饰者模式的精髓。这也是装饰者模式开扩展闭修改的精髓。
咖啡示例参考代码
//咖啡类以及装饰者类的基类
public abstract class Beverage {
public String description;
public String getDescription(){
return description;
}
public abstract double cost();
}
//咖啡类
public class DarkRoast extends Beverage {
@Override
public double cost() {
return 10.0;
}
}
//装饰者基类
public class CondimentDecorator extends Beverage{
public Beverage beverage;
public CondimentDecorator(Beverage beverage) {
this.beverage = beverage;
}
@Override
public double cost() {
return 0;
}
}
//加料牛奶类
public class Milk extends CondimentDecorator {
public Milk(Beverage beverage) {
super(beverage);
}
@Override
public double cost() {
return this.beverage.cost() + 5;
}
}
//加料泡泡类
public class Whip extends CondimentDecorator {
public Whip(Beverage beverage) {
super(beverage);
}
@Override
public double cost() {
return this.beverage.cost() + 3;
}
}
//测试类
public class Test {
public static void main(String[] args) {
DarkRoast darkRoast = new DarkRoast();
Milk milk1 = new Milk(darkRoast);
Milk milk2 = new Milk(milk1);
Whip whip = new Whip(milk2);
System.out.println(whip.cost());//输出23.0
}
}