理解装饰模式

Lucene的分词器中使用了装饰模式,之前不太理解,今天花点时间消化一下。

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

UML图

 

 

举个例子:

假如你是卖手抓饼的,你卖两种手抓饼,大号和小号,同时买家可以随意加生菜,鸡蛋,火腿肠,培根等。

如果用继承,想想有多麻烦。这时装饰模式就派上用场了,代码如下:

 

 

  1 public class Program {
  2 
  3     /**
  4      * @param args
  5      */
  6     public static void main(String[] args) {
  7 
  8         // 路人甲
  9         Program p1 = new Program();
 10         // 购买大号手抓饼
 11         Pastry pastry = p1.new BigPastry();
 12         // 加生菜(生菜修饰手抓饼)
 13         Pastry lettuce = p1.new Lettuce(pastry);
 14         // 加培根(培根修饰加了生菜的手抓饼)
 15         Pastry bacon = p1.new Bacon(lettuce);
 16 
 17         System.out.println("路人甲买饼");
 18         System.out.println(bacon.getName());
 19         System.out.println(bacon.getPrice());
 20         System.err.println("***********");
 21 
 22         // 路人乙
 23         Program p2 = new Program();
 24         // 购买小号手抓饼
 25         pastry = p1.new SmallPastry();
 26         // 加蛋(鸡蛋修饰小号手抓饼)
 27         Pastry egg = p2.new Egg(pastry);
 28         // 加生菜(生菜修饰加蛋的手抓饼)
 29         lettuce = p2.new Lettuce(egg);
 30         // 加培根(培根修饰加了蛋和生菜的手抓饼)
 31         bacon = p2.new Bacon(lettuce);
 32 
 33         System.out.println("路人乙买饼");
 34         System.out.println(bacon.getName());
 35         System.out.println(bacon.getPrice());
 36 
 37     }
 38 
 39     /**
 40      * 
 41      * 手抓饼
 42      * 
 43      */
 44     public abstract class Pastry {
 45 
 46         protected String name;
 47 
 48         public String getName() {
 49             return name;
 50         }
 51 
 52         protected double price;
 53 
 54         public abstract double getPrice();
 55     }
 56 
 57     /**
 58      * 
 59      * 附加物
 60      * 
 61      */
 62     public abstract class Attachment extends Pastry {
 63 
 64         protected Pastry pastry;
 65 
 66         public Attachment(Pastry pastry) {
 67             this.pastry = pastry;
 68         }
 69 
 70         @Override
 71         public double getPrice() {
 72             return pastry.getPrice() + price;
 73         }
 74 
 75     }
 76 
 77     /**
 78      * 
 79      * 大号手抓饼,5元一个
 80      * 
 81      */
 82     public class BigPastry extends Pastry {
 83 
 84         public BigPastry() {
 85             name = "大号手抓饼(5元) ";
 86         }
 87 
 88         @Override
 89         public double getPrice() {
 90             return 5.0;
 91         }
 92 
 93     }
 94 
 95     /**
 96      * 
 97      * 小号手抓饼,3元一个
 98      * 
 99      */
100     public class SmallPastry extends Pastry {
101 
102         public SmallPastry() {
103             name = "小号手抓饼(3元) ";
104         }
105 
106         @Override
107         public double getPrice() {
108             return 3.0;
109         }
110 
111     }
112 
113     /**
114      * 
115      * 生菜5毛
116      * 
117      */
118     public class Lettuce extends Attachment {
119 
120         public Lettuce(Pastry pastry) {
121             super(pastry);
122             price = 0.5;
123             name = pastry.getName() + " 生菜(5毛),";
124         }
125 
126     }
127 
128     /**
129      * 
130      * 火腿肠1元
131      * 
132      */
133     public class Ham extends Attachment {
134 
135         public Ham(Pastry pastry) {
136             super(pastry);
137             price = 1.0;
138             name = pastry.getName() + "火腿肠(1元),";
139         }
140     }
141 
142     /**
143      * 
144      * 培根2元
145      * 
146      */
147     public class Bacon extends Attachment {
148 
149         public Bacon(Pastry pastry) {
150             super(pastry);
151             price = 2.0;
152             name = pastry.getName() + "培根(2元),";
153         }
154 
155     }
156 
157     /**
158      * 
159      * 鸡蛋1元
160      * 
161      */
162     public class Egg extends Attachment {
163 
164         public Egg(Pastry pastry) {
165             super(pastry);
166             price = 1.0;
167             name = pastry.getName() + "鸡蛋(1元),";
168         }
169 
170     }
171 
172 }

 

posted @ 2013-10-12 14:03  sam zeng6  阅读(256)  评论(0)    收藏  举报