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

