设计模式 -- 装饰者模式

 装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加有弹性的替代方案。

对于我自己的理解:装饰者模式就是一个在继承层面上的递归。

对于装饰者模式而言,有两个很重要的概念: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

 

posted @ 2017-03-22 15:37  Artemis29  阅读(211)  评论(0编辑  收藏  举报