Java设计模式——装饰者模式
2016-06-02 01:11
513 查看
愉快的工作又开始了。Leader安排了一个新的任务,给一个酸奶店的点单软件增加新的功能。
这个程序的原来所有的酸奶都继承于奶酪类(Cheese)
所有具体的酸奶继承奶酪类并重写价格price方法,以原味酸奶和宫廷酸奶为例:
这样的话直接调用实现类的introduce和price就可以得到名字和价格了。
但是随着酸奶店的规模越来越大,品种也越来越多,出现了一些新的品种的酸奶和配料,比如:草莓,奥利奥,樱桃。这些配料和酸奶进行搭配然后计算总共的价格和名称。
稍微思考一下,可能会有人选择这样写代码,以原味酸奶加草莓为例:
这样看起来,似乎并没有什么不妥,但是仔细想一想,酸奶加配料这样的组合有多少种可能呢?如果每一种可能都要写出来一个类的话,那么简直要类爆炸,并且如果任何一个酸奶或者配料更改了价格的话,那么所有关联类都需要修改,如果顾客想要双倍的草莓呢?或者草莓加樱桃呢?这样写下去简直是反人类的方法。
设计原则之一:类应该对扩展开发,对修改关闭。比如说对于一些我们经过测试没有问题的代码,原则上不应该修改源代码,而应该在源代码基础之上进行扩展。
如果我们这样设计代码是不是更好一点,还是以原味酸奶加草莓为例:我们先把一杯原味酸奶作为主体(被修饰者),用草莓作为修饰者修饰主体。就是先得到一个原味酸奶的对象,用草莓对象修饰它,然后调用price方法将草莓的价钱加上去。
这样的做法可以动态的将奶酪和配料松耦合的搭配在一起。所以先把系统分为奶酪和配料两个部分。
草莓的实现类如下:
樱桃的实现类如下:
以原味酸奶加草莓为例:
输出结果:Original,Strawberry12
这个程序的原来所有的酸奶都继承于奶酪类(Cheese)
public abstract class Cheese { public String name; public String introduce(){ return name; } public abstract int price();
所有具体的酸奶继承奶酪类并重写价格price方法,以原味酸奶和宫廷酸奶为例:
public class Original extends Cheese{ public Original() { name="Original"; } @Override public int price() { return 10; } } public class Court extends Cheese{ public Court() { name="Court"; } @Override public int price() { return 8; } }
这样的话直接调用实现类的introduce和price就可以得到名字和价格了。
但是随着酸奶店的规模越来越大,品种也越来越多,出现了一些新的品种的酸奶和配料,比如:草莓,奥利奥,樱桃。这些配料和酸奶进行搭配然后计算总共的价格和名称。
稍微思考一下,可能会有人选择这样写代码,以原味酸奶加草莓为例:
public class OriginalStrawberry extends Cheese{ public Original() { name="OriginalStrawberry "; } @Override public int price() { return 10; } }
这样看起来,似乎并没有什么不妥,但是仔细想一想,酸奶加配料这样的组合有多少种可能呢?如果每一种可能都要写出来一个类的话,那么简直要类爆炸,并且如果任何一个酸奶或者配料更改了价格的话,那么所有关联类都需要修改,如果顾客想要双倍的草莓呢?或者草莓加樱桃呢?这样写下去简直是反人类的方法。
设计原则之一:类应该对扩展开发,对修改关闭。比如说对于一些我们经过测试没有问题的代码,原则上不应该修改源代码,而应该在源代码基础之上进行扩展。
如果我们这样设计代码是不是更好一点,还是以原味酸奶加草莓为例:我们先把一杯原味酸奶作为主体(被修饰者),用草莓作为修饰者修饰主体。就是先得到一个原味酸奶的对象,用草莓对象修饰它,然后调用price方法将草莓的价钱加上去。
这样的做法可以动态的将奶酪和配料松耦合的搭配在一起。所以先把系统分为奶酪和配料两个部分。
public abstract class Batching extends Cheese { public abstract String introduce(); }
草莓的实现类如下:
public class Strawberry extends Batching { Cheese cheese; public Strawberry(Cheese cheese) { this.cheese = cheese; } @Override public int price() { return(cheese.price()+2); } @Override public String introduce() { return(cheese.introduce()+",Strawberry"); } }
樱桃的实现类如下:
public class Cherry extends Batching{ Cheese cheese; public Cherry(Cheese cheese) { this.cheese = cheese; } @Override public String introduce() { return cheese.introduce()+"Cherry"; } @Override public int price() { return cheese.price()+3; } }
以原味酸奶加草莓为例:
public class Test { public static void main(String[] a){ Cheese cheese=new Original(); cheese =new Strawberry(cheese); System.out.println(cheese.introduce()+cheese.price()); } }
输出结果:Original,Strawberry12
相关文章推荐
- [Java Concurrent] 并发访问共享资源的简单案例
- 查看.class文件的版本号
- 基于Spring4+Hibernate4的通用数据访问层+业务逻辑层(Dao层+Service层)设计与实现!
- (Java)LeetCode-23. Merge k Sorted Lists
- struts2框架报错记录二
- Java多线程-线程同步问题
- java将固定长度的byte数组转成String,并去掉后面多余的0
- java读取xml(DOM解析)
- jvm学习-垃圾收集
- eclipse中Server视图加载项目之后项目名后边有带括号的名字
- 10个实用的但偏执的Java编程技术
- Java高效读取大文件
- Spring 返回Json
- Web图表控件ChartDirector使用教程:轻松创建Java图表应用程序
- JBoss与jdk版本
- Exception in thread "main" java.lang.NoClassDefFou
- Java Zip 压缩、解压
- SpringMVC学习笔记(7):处理模型数据(2)
- JAVA原子性操作
- 有关JAVA虚拟机规范的官方文档 收藏