定义
装饰者模式动态的将责任附加在对象上. 若要拓展功能, 装饰者提供了比继承更有弹性的替代方案.
特点:
- 装饰者和被装饰对象有共同的超类型
- 可以用一个或多个装饰者包装一个对象
- 既然装饰者与被装饰对象有着相同的超类型, 所以在任何需要原始对象(被包装)的场合, 可以用装饰过的对象代替它
- 装饰者可以在所委托被装饰者的行为之前与/或之后, 加上自己的行为, 以达到特定的目的
- 对象可以在任何时候被装饰, 所以可以在运行时动态的, 不限量的用你喜欢的装饰者来装饰对象
设计原则
- 类应该对拓展开放, 对修改关闭
案例
背景: 酒吧卖酒, 酒Beverage是抽象类, 酒有很多子类,需要计算成本, 子类的调料并不相同
现将计算成本的方法cost()在父类中声明, 子类重写调料的方法
Beverage
public abstract class Beverage {
protected abstract boolean hasMilk();
protected abstract boolean hasSoy();
private Integer money;
public Integer getMoney() {
return money;
}
public void setMoney(Integer money) {
this.money = money;
}
public Integer cost() {
if (hasMilk()) {
this.money += 1;
}
if (hasSoy()) {
this.money += 2;
}
return this.money;
}
}
HouseBlend
public class HouseBlend extends Beverage {
@Override
protected boolean hasMilk() {
return true;
}
@Override
protected boolean hasSoy() {
return false;
}
}
测试
@Test
public void testDecorator() {
HouseBlend houseBlend = new HouseBlend();
houseBlend.setMoney(0);
System.out.println("houseBlend的成本为: " + houseBlend.cost());
DarkRoust darkRoust = new DarkRoust();
darkRoust.setMoney(0);
System.out.println("darkRoust的成本为: " + darkRoust.cost());
}
结果:
houseBlend的成本为: 1
darkRoust的成本为: 2
问题:
出现新的调料, 需要在父类中添加新的方法, 并更改cost方法
改用装饰者模式后
被装饰者顶层抽象类
public abstract class Beverage {
public abstract Integer cost();
}
被装饰者
public class DarkRoust extends Beverage {
@Override
public Integer cost() {
return 10;
}
}
public class HouseBlend extends Beverage {
@Override
public Integer cost() {
return 20;
}
}
装饰者
现有一个抽象类保证 装饰者与被装饰者类型一致
public abstract class CondimentDecorator extends Beverage {
}
装饰者持有被装饰者的属性, 在构造方法中传入,当然也可以动态set
Milk
public class Milk extends CondimentDecorator {
private Beverage beverage;
public Milk(Beverage beverage) {
this.beverage = beverage;
}
@Override
public Integer cost() {
return 2 + beverage.cost();
}
public Beverage getBeverage() {
return beverage;
}
public void setBeverage(Beverage beverage) {
this.beverage = beverage;
}
}
@Override
public Integer cost() {
return 2 + beverage.cost();
}
}
Soy, 注意可以”层层包装”
public class Soy extends CondimentDecorator {
private Beverage beverage;
public Soy(Beverage beverage) {
this.beverage = beverage;
}
@Override
public Integer cost() {
return 1 + beverage.cost();
}
public Beverage getBeverage() {
return beverage;
}
public void setBeverage(Beverage beverage) {
this.beverage = beverage;
}
}
测试
@Test
public void testDecorator() {
//darkRoust成本10,houseBlend成本20
//milk成本1,soy成本2
// darkRoust加milk和soy
DarkRoust darkRoust = new DarkRoust();
Milk milk = new Milk(darkRoust);
Soy soy = new Soy(milk);
System.out.println("darkRoust的成本为: " + milk.cost());
// houseBlend只加soy
HouseBlend houseBlend = new HouseBlend();
Soy soy1 = new Soy(houseBlend);
System.out.println("houseBlend的成本为: " + soy.cost());
}
结果:
darkRoust的成本为: 12
houseBlend的成本为: 13