java设计模式之装饰模式趣谈-mile米乐体育
本文由码农网 – 鲁阿皓原创,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划!
前情提要:http://blog.
jvm:”上次给我招的工人不错啊!”
oo程序员:”………..”
jvm:”现在来我开的博物馆生意越来越好了,原来”舞台剧”的方式已经不能满足顾客的需求了”
oo程序员:”………..”
jvm:”我决定要换一种运营模式,把每个演播厅都租出去,让那些想表演节目的对象们来租演播厅和相关器械,这样我就能坐地收钱了!”
oo程序员:”………..”
jvm:”合伙干吧?怎么样?你三我七!”
oo程序员:”………..”
jvm:”四六?”
oo程序员:”成交!先说说需求。”
jvm:”首先有不同类型的演播厅和不同的装饰品/器械,每种物品都要付一定的租金,你要做的就是一件事,把总租金(演播厅 饰品/器械)算出来。”
oo程序员:”把价格表给我!”
卡通演播厅(cartoonstudio) 100
小丑演播厅(jokerstudio) 150
超级演播厅(superstudio) 300
气球(balloon) 10
灯光(lamplight) 25
麦克风(microphone) 20
最后还写下了这个:
public abstract class anything_ex() { string description=" "; public string getdescription() { return description; } public abstract int cost(); }
仔细一想也对,无论是演播厅还是装饰品,都需要描述(description)和cost(价格),写一个共同的父类无可厚非。
接着写下你设计的第一个类:
class cartoonandballoon extends anything_ex { .... public int cost() { return 100 10; } } //带气球的卡通演播厅
第二个:
class cartoonandlamplight extends anything_ex { ... public int cost() { return 100 25; } } //带灯光的卡通演播厅
第三个:
。。。。。
没有第三个了!这样写下去可是无穷无尽的!没办法,换个思路。
在演播厅里,无论什么装饰品都有可能出现,可以把演播厅 饰品看成一个整体,通过饰品相应的has和set来控制饰品,这样的话,设计出来的类如下:
class cartoonstudio extends anything_ex { private boolean balloon=false; .... //省略其他变量,这里只以气球为例 public boolean hasballoon() { return ballon; } public void setballon() { balloon=true; } .......//省略其他has/set方法 public int cost() { int cost=100; //卡通演播厅的初始价格为100 if(hasballoon) { cost =10; } else if(hasxxx).....//省略类推下来的代码 return cost; } }
这个看起来好多了,不用写大爆炸数量的类,虽然类写起来又臭(无数的has/set)又长(的确很长)。。。。。
但是有没有更好的方案?
答案当然是有的,不过我们必须先明确一下,上述设计的缺点。
- 1.臭
- 2.长
- 3.当饰品的租金改变的时候,必须修改所有演播厅的代码(cost部分),我们当然不想这样,我们想尽可能的少修改代码(松耦合)。
- 4.没有面对超类/接口编程。
- 5.没有将变化的部分独立开。
- 6.组合可能是更好的mile米乐体育的解决方案。
下面让我们看看。装饰者模式是如何解决上面问题的。
装饰者模式:动态的将责任加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
首先,我们先将演播厅和他的装饰者们分开,让装饰者继承另一个类:
public abstract class decorater_ex extends anyting_ex { public abstract string getdescription(); }
让装饰者子类重新实现getdescription()即可。
现在我们的思路是:用装饰者装饰演播厅,例如,一个带麦克风和气球的卡通演播厅,就先让气球装饰卡通演播厅,再让麦克风装饰“带气球的卡通演播厅”
先让我们分别实现这3个类:
卡通演播厅:
class cortoonstudio extends anything_ex { public cortoonstudio() { description="cortonstudio"; } publuc int cost() { return 100; } }
麦克风:
class microphone extends decorater_ex { private anything_ex studio; public microphone(anything_ex studio ) { this.studio=studio; } public string getdescription() { return studio.getdescription() ",microphone"; } public int cost() { return studio.cost() 20; } }
气球:
class balloon extends decorater_ex { private anything_ex studio; public balloon(anything_ex studio ) { this.studio=studio; } public string getdescription() { return studio.getdescription() ",balloon"; } public int cost() { return studio.cost() 10 ; } }
代码:
anything_ex cortoonstudio =new cortoonstudio(); //一个卡通演播厅对象 cortoonstudio=new microphone(cortoonstudio); //拿麦克风装饰 cortoonstudio=new balloon(cortoonstudio); //拿气球装饰 system.out.println(cortoonstudio.getdescription() "=" cortoonstudio.cost());
输出结果:
cortonstudio,microphone,balloon=130
结果是正确的。
这样写很好的解决了上面的问题。
- 1.运用组合进行扩展,使当价格改变的时候,只需要修改本身的代码。
- 2.面对超类/接口编程,使饰品增加种类的时候,并不需要修改被装饰者的代码。
- 3.开放——关闭原则 :代码应该对扩展开放,对修改关闭。
缺陷:
- 1.子类繁多,影响理解代码(java i/o就是装饰者模式哦。。。)。
- 2.无法应用于需要具体类的场景。
这篇文章到此差不多结束了,作者功力尚浅,文章如有不正之处请读者指出,海涵。
本文链接:http://www.codeceo.com/article/java-decorator-pattern.html
本文作者:码农网 – 鲁阿皓
[ 原创作品,转载必须在正文中标注并保留原文链接和作者等信息。]