设计模式 -- 装饰者模式
装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加有弹性的替代方案。
对于我自己的理解:装饰者模式就是一个在继承层面上的递归。
对于装饰者模式而言,有两个很重要的概念:component 与 decorator;
component (组件):被装饰的主体
decorator(装饰者):用于装饰主体的配件
下面我们来用一个咖啡馆的订单系统作为实例。
咖啡馆需求:根据客户的订单,生成价格。而客户可选择一个单品咖啡,并且可以在这个选择的单品咖啡上添加相应装饰(牛奶、奶泡、茶....etc)
根据上面的需求,我们应用装饰者模式去实现。
类图:
注意:标准的装饰者模式是没有 coffeeComponent 这一层的~ 这里是为了实现更加便捷、清晰而添加上去的。
代码实现:
AbstractCoffeeComponent :component,被装饰的组件
1 package decorator.component; 2 3 /** 4 * Created by chenjiayin on 2017/3/18. 5 */ 6 public abstract class AbstractCoffeeComponent 7 { 8 public String description; 9 private double price; 10 11 public String getDescription() 12 { 13 return description + ":" + this.getPrice(); 14 } 15 16 public void setDescription(String description) 17 { 18 this.description = description; 19 } 20 21 public double getPrice() 22 { 23 return price; 24 } 25 26 public void setPrice(double price) 27 { 28 this.price = price; 29 } 30 31 public abstract double cost(); 32 }
CoffeeComponent :抽取这一层,cost()里面的价格就是它本身的价格,因为点单品只会点一个单品的。。。两个单品混合的咖啡不在本次需求的考虑范围内
1 package decorator.component; 2 3 /** 4 * Created by chenjiayin on 2017/3/18. 5 */ 6 public class CoffeeComponent extends AbstractCoffeeComponent 7 { 8 @Override 9 public double cost() 10 { 11 return super.getPrice(); 12 } 13 }
单品咖啡,Decaf
1 package decorator.component; 2 3 /** 4 * Created by chenjiayin on 2017/3/18. 5 */ 6 public class Decaf extends CoffeeComponent 7 { 8 public Decaf() 9 { 10 super.setDescription("Decaf"); 11 super.setPrice(30); 12 } 13 }
单品咖啡,Expresso
1 package decorator.component; 2 3 /** 4 * Created by chenjiayin on 2017/3/18. 5 */ 6 public class Expresso extends CoffeeComponent 7 { 8 public Expresso() 9 { 10 super.setDescription("Expresso"); 11 super.setPrice(31); 12 } 13 }
单品咖啡,LongBlack
1 package decorator.component; 2 3 /** 4 * Created by chenjiayin on 2017/3/18. 5 */ 6 public class LongBlack extends CoffeeComponent 7 { 8 public LongBlack() 9 { 10 super.setDescription("LongBlack"); 11 super.setPrice(32); 12 } 13 }
单品咖啡,ShortBlack
1 package decorator.component; 2 3 /** 4 * Created by chenjiayin on 2017/3/18. 5 */ 6 public class ShortBlack extends CoffeeComponent 7 { 8 public ShortBlack() 9 { 10 super.setDescription("ShortBlack"); 11 super.setPrice(33); 12 } 13 }
好了,上面,我们已经将我们需要的组件都已经定义好了,下面,我们开始定义装饰者了。
AbstractCoffeeDecorator:装饰者的抽象类,继承了组件,并且以组件作为它的一个属性,因为需要装饰它。
1 package decorator.decorator; 2 3 import decorator.component.AbstractCoffeeComponent; 4 5 /** 6 * Created by chenjiayin on 2017/3/18. 7 */ 8 public abstract class AbstractCoffeeDecorator extends AbstractCoffeeComponent 9 { 10 private AbstractCoffeeComponent coffeeComponent; 11 12 public AbstractCoffeeDecorator(AbstractCoffeeComponent coffeeComponent) 13 { 14 this.coffeeComponent = coffeeComponent; 15 } 16 17 @Override 18 public double cost() 19 { 20 return super.getPrice() + coffeeComponent.cost(); 21 } 22 23 @Override 24 public String getDescription() 25 { 26 return super.getDescription() + "+" + coffeeComponent.getDescription(); 27 } 28 }
装饰者,Milk
1 package decorator.decorator; 2 3 import decorator.component.AbstractCoffeeComponent; 4 5 /** 6 * Created by chenjiayin on 2017/3/18. 7 */ 8 public class Milk extends AbstractCoffeeDecorator 9 { 10 public Milk(AbstractCoffeeComponent coffeeComponent) 11 { 12 super(coffeeComponent); 13 super.setDescription("Milk"); 14 super.setPrice(5); 15 } 16 }
装饰者,Whip
1 package decorator.decorator; 2 3 import decorator.component.AbstractCoffeeComponent; 4 5 /** 6 * Created by chenjiayin on 2017/3/18. 7 */ 8 public class Whip extends AbstractCoffeeDecorator 9 { 10 public Whip(AbstractCoffeeComponent coffeeComponent) 11 { 12 super(coffeeComponent); 13 super.setDescription("Whip"); 14 super.setPrice(3); 15 } 16 }
装饰者,Tea
1 package decorator.decorator; 2 3 import decorator.component.AbstractCoffeeComponent; 4 5 /** 6 * Created by chenjiayin on 2017/3/18. 7 */ 8 public class Tea extends AbstractCoffeeDecorator 9 { 10 public Tea(AbstractCoffeeComponent coffeeComponent) 11 { 12 super(coffeeComponent); 13 super.setDescription("Tea"); 14 super.setPrice(10); 15 } 16 }
我们的装饰者,与我们的组件都已经定义好了,我们来看一下成果。
测试类,DecoratorMain
1 package decorator; 2 3 import decorator.component.AbstractCoffeeComponent; 4 import decorator.component.Decaf; 5 import decorator.component.Expresso; 6 import decorator.decorator.Milk; 7 import decorator.decorator.Tea; 8 import decorator.decorator.Whip; 9 10 /** 11 * Created by chenjiayin on 2017/3/18. 12 */ 13 public class DecoratorMain 14 { 15 public static void main(String[] args) 16 { 17 AbstractCoffeeComponent fatCatCoffeeOrder; 18 fatCatCoffeeOrder = new Expresso(); 19 fatCatCoffeeOrder = new Milk(fatCatCoffeeOrder); 20 System.out.println("order desc:" + fatCatCoffeeOrder.getDescription()); 21 System.out.println("order price:" + fatCatCoffeeOrder.cost()); 22 23 24 AbstractCoffeeComponent thinCatCoffeeOrder; 25 thinCatCoffeeOrder = new Decaf(); 26 thinCatCoffeeOrder = new Whip(thinCatCoffeeOrder); 27 thinCatCoffeeOrder = new Whip(thinCatCoffeeOrder); 28 thinCatCoffeeOrder = new Tea(thinCatCoffeeOrder); 29 System.out.println("order desc:" + thinCatCoffeeOrder.getDescription()); 30 System.out.println("order price:" + thinCatCoffeeOrder.cost()); 31 32 } 33 }
输出结果:
1 order desc:Milk:5.0+Expresso:31.0 2 order price:36.0 3 order desc:Tea:10.0+Whip:3.0+Whip:3.0+Decaf:30.0 4 order price:46.0