设计原理5:类应该对扩展开放,对修改关闭
装饰者模式:动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案
案例,根据《Head First》的例子,写一个茶与调味料- 糖和牛奶的例子:
斜体文字的为虚类或虚函数。
代码实现:
public class PatternDemo { public static void main(String[] args) { Tea tea = new Tea(); System.out.println(tea.getDescription() + ", $" + tea.getCost()); Beverage beverage = new Milk(tea); Beverage beverage1 = new Sugar(tea); System.out.println(beverage.getDescription() + ", $" + beverage.getCost()); System.out.println(beverage1.getDescription() + ", $" + beverage1.getCost()); beverage = new Sugar(beverage); System.out.println(beverage.getDescription() + ", $" + beverage.getCost()); } }
public abstract class Beverage { private String description; public Beverage() { } public Beverage(String description) { this.description = description; } public String getDescription() { return description; } public abstract double getCost(); }
public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); }
public class Tea extends Beverage { public Tea() { super("Tea"); } public Tea(String description) { super(description); } @Override public double getCost() { return 2; } }
public class Milk extends CondimentDecorator { private Beverage beverage; public Milk(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription() + " with milk"; } @Override public double getCost() { return beverage.getCost() + 0.5; } }
public class Sugar extends CondimentDecorator { private Beverage beverage; public Sugar(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription() + " with sugar"; } @Override public double getCost() { return beverage.getCost() + 0.3; } }
《Head First》后面提到,原来JDK里的InputStream和OutputStream都是用装饰者模式完成的,这样就好理解多了:
InputStream就是最上层的抽象基类,而FilterInputStream就是继承抽象基类InputStream的装饰者抽象基类