1、定义:装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
2、满足OO设计原则——开放-关闭原则:类应该对扩展开放,对修改关闭。
注:装饰者模式是一个简单的能够实现开放-关闭原则的设计模式
3、优点:
- 能够遵循开放-关闭原则,使系统更有弹性
- 组合和委托可以用于在运行时动态地加上新的行为
- 装饰者类反映出被装饰的组件类型(事实上,它们具有相同的类型,都经过接口或集成实现)
- 装饰者可以再被装饰者的行为前面与/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的。
4、缺点:装饰者会导致设计中出现许多小对象,如果过度使用,会让程序变得很复杂。
5、具体实现(完整代码保存在github上):
- 抽象组件类:
//饮料超类 public abstract class Beverage{ String description = "Unknown Beverage"; public String getDescription(){ return description; } public abstract double cost(); }
- 具体组件类:
//饮料:深焙 public class DarkRoast extends Beverage{ public DarkRoast(){ description = "DarkRoast"; } public double cost(){ return .99; } } //饮料:低咖啡因 public class Decaf extends Beverage{ public Decaf(){ description = "Decaf"; } public double cost(){ return 1.05; } } //饮料:浓缩 public class Espresso extends Beverage{ public Espresso(){ description = "Espresso"; } public double cost(){ return 1.99; } } //饮料:综合 public class HouseBlend extends Beverage{ public HouseBlend(){ description = "House Blend coffee"; } public double cost(){ return .89; } }
- 抽象装饰者类:
//调料都继承自这里 public abstract class CondimentDecorator extends Beverage{ public abstract String getDescription(); }
- 具体装饰者类:
//调料:牛奶 public class Milk extends CondimentDecorator{ Beverage beverage; public Milk(Beverage beverage){ this.beverage = beverage; } public String getDescription(){ return beverage.getDescription() + ",Milk"; } public double cost(){ return .10 + beverage.cost(); } } //调料:摩卡 public class Mocha extends CondimentDecorator{ Beverage beverage; public Mocha(Beverage beverage){ this.beverage = beverage; } public String getDescription(){ return beverage.getDescription() + ",Mocha"; } public double cost(){ return .20 + beverage.cost(); } } //调料:豆浆 public class Soy extends CondimentDecorator{ Beverage beverage; public Soy(Beverage beverage){ this.beverage = beverage; } public String getDescription(){ return beverage.getDescription() + ",Soy"; } public double cost(){ return .15 + beverage.cost(); } //调料:奶泡 public class Whip extends CondimentDecorator{ Beverage beverage; public Whip(Beverage beverage){ this.beverage = beverage; } public String getDescription(){ return beverage.getDescription() + ",Whip"; } public double cost(){ return .10 + beverage.cost(); } }
- 测试:
public class StarbuzzCoffee{ public static void main(String args[]){ Beverage beverage = new Espresso(); System.out.println(beverage.getDescription() + " $" + beverage.cost()); Beverage beverage2 = new DarkRoast(); beverage2 = new Mocha(beverage2); beverage2 = new Mocha(beverage2); beverage2 = new Whip(beverage2); System.out.println(beverage2.getDescription() + " $" + beverage2.cost()); Beverage beverage3 = new HouseBlend(); beverage3 = new Soy(beverage3); beverage3 = new Mocha(beverage3); beverage3 = new Whip(beverage3); System.out.println(beverage3.getDescription() + " $" + beverage3.cost()); } }
运行结果如下图所示:
参考资料
[1] head first 设计模式