1 什么是装饰者模式
装饰者模式:动态地将责任附加到对象上。若要扩展功能,装饰着提供了比继承更有弹性的替代方案。
这虽然说明了装饰着模式的“角色”,但是没说明怎么在我们的实现中实际应用它,下面举一个简单的例子。
2 为什么不用继承
我们就举星巴克的例子。
在购买饮料的时候,除了我们可以选择像DarkRoast(深度烘焙)以外,我们还可以加东西,比如说燕麦、豆奶,如果我们使用继承,很可能就成了如下这个样子:
3 类应该对扩展开放,对修改关闭
有人可能有这个想法,为什么我们不把所有的调料都放到Beverage里面,通过getter and setter method来设置它是否加入?其实也可以,但一旦你的功能进行扩展,比如说现在要加入大杯或者小杯的机制怎么办?现在要加入外卖或者在店里喝又该怎么办?
所以说有这样一句话:类应该对扩展开放,对修改关闭
4 开始装饰者模式
一句话:小类包大类
还是拿星巴克举例子,我们现在要一个摩卡咖啡,加奶泡,深度烘焙。
- 拿一个深度烘焙咖啡为对象(DarkRoast)
- 以摩卡对象装饰他
- 以奶泡对象装饰他
- 计算加钱
5 装饰者模式要点
- 装饰者和被装饰对象有相同的超类型
- 你可以用一个或者多个装饰者包装一个对象
- 既然装饰者和被装饰的对象有相同的超类型,所以在任何需要原始对象(被包装)的场合,可以用装饰过的对象替代他
- 装饰者可以在所委托被装饰者的行为之前或者之后,加上自己的行为,以达到特定的目的
6 我们的例子
抽象基类
public abstract class Beverage {
protected String desc = "unknown beverage";
public String getDesc() {
return desc;
}
public abstract double cost();
}
装饰者类
public abstract class CondimentDecorator extends Beverage {
public abstract String getDesc();
}
DarkRoast 类
public class DarkRoast extends Beverage {
@Override
public double cost() {
return 1.0;
}
public DarkRoast() {
desc = "dark roast";
}
}
Moca
public class Moca extends CondimentDecorator {
Beverage beverage;
public Moca(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDesc() {
return beverage.getDesc()+"and Moca";
}
@Override
public double cost() {
return beverage.cost()+0.5;
}
}
Milk
public class Milk extends CondimentDecorator {
Beverage beverage;
public Milk(Beverage beverage) {
this.beverage = beverage;
}
@Override
public double cost() {
return beverage.cost()+0.8;
}
@Override
public String getDesc() {
// TODO Auto-generated method stub
return beverage.getDesc()+" and Mike";
}
}
测试
public class MyTest {
public static void main(String[] args) {
Beverage beverage = new DarkRoast();
beverage = new Moca(beverage);
beverage = new Milk(beverage);
System.out.println(beverage.getDesc());
System.out.println(beverage.cost());
}
}