设计模式学习笔记之三:装饰者模式
公司门口有一个小摊卖手抓饼和肉夹馍的,有时候中午不想吃饭就会去光顾一下那个小摊,点了手抓饼之后往往还可以在这个基础之上增加一些配料,例如煎蛋,火腿片等等,每个配料的价格都不一样,不管你怎么配配料,最终价格是手抓饼基础价加上每一种所选配料价格的总和。小摊的价格单如下:
如何使用一种设计模式来处理价格计算的问题呢,或许我们可以试试装饰者模式,因为在这里,主体是手抓饼和肉夹馍,而配料则是装饰者,我先用UML类图来描述一下类之间的协作关系。
再来看看具体java代码是怎么实现的:
1 public abstract class Pancake { 2 3 public String desc = "我不是一个具体的煎饼"; 4 5 public String getDesc() { 6 return desc; 7 } 8 9 public abstract double price(); 10 11 }
public class TornCake extends Pancake { public TornCake() { desc = "手抓饼"; } @Override public double price() { return 4; } }
public class Roujiamo extends Pancake { public Roujiamo() { desc = "肉夹馍"; } @Override public double price() { return 6; } }
public abstract class Condiment extends Pancake { public abstract String getDesc(); }
public class FiredEgg extends Condiment { private Pancake pancake; public FiredEgg(Pancake pancake) { this.pancake = pancake; } @Override public String getDesc() { return pancake.getDesc() + ", 煎蛋"; } @Override public double price() { return pancake.price() + 2; } }
public class Ham extends Condiment { private Pancake pancake; public Ham(Pancake pancake) { this.pancake = pancake; } @Override public String getDesc() { return pancake.getDesc() + ", 火腿片"; } @Override public double price() { return pancake.price() + 1.5; } }
MeatFloss类和Cucumber类跟FiredEgg很相似,我就不一一列出来了,最后看看测试类:
public class MyTest { @Test public void test() { Pancake tornCake = new TornCake(); //手抓饼基础价 System.out.println(String.format("%s ¥%s", tornCake.getDesc(), tornCake.price())); Pancake roujiamo = new Roujiamo(); roujiamo = new FiredEgg(roujiamo); roujiamo = new FiredEgg(roujiamo); roujiamo = new Ham(roujiamo); roujiamo = new MeatFloss(roujiamo); roujiamo = new Cucumber(roujiamo); //我好饿 System.out.println(String.format("%s ¥%s", roujiamo.getDesc(), roujiamo.price())); } }
在Java源码中典型的装饰者模式就是java I/O, 其实装饰者模式也有其缺点,就是产生了太多的装饰者小类,有类爆炸的趋势。
我是刚学设计模式的小白,欢迎各位拍砖:)