Java设计模式之装饰模式趣谈
本文由码农网 – 鲁阿皓原创,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划!
前情提要:http://blog.csdn.net/baidu_30889437/article/details/50917814
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.组合可能是更好的解决方案。
下面让我们看看。装饰者模式是如何解决上面问题的。
装饰者模式:动态的将责任加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
首先,我们先将演播厅和他的装饰者们分开,让装饰者继承另一个类:
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.无法应用于需要具体类的场景。
这篇文章到此差不多结束了,作者功力尚浅,文章如有不正之处请读者指出,海涵。
Java设计模式之装饰模式趣谈的更多相关文章
- java设计模式学习笔记--浅谈设计模式
设计模式的目的 编写软件的过程中,程序员面临着来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战.设计模式为了让程序具有更好的 1.代码重用性(即:相同功能的代码,不用多次编写) ...
- java设计模式之装饰模式
发现设计模式的学习越来越让自己学习的东西太少了,应该多接触一些东西,多出去走一走. 装饰模式概念: 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活(大话设计模式) 在不 ...
- Java——设计模式(装饰模式_IO)
/* * 装饰设计模式: * 对一组对象的功能进行增强时,就可以使用该模式进行问题的解决; * 装饰和继承都能实现一样的特点: 就是进行功能的扩转增强. * */ public class ...
- JAVA设计模式:装饰模式
前面我们学习了代理模式: 代理模式主要使用了java的多态,干活的是被代理类,代理类主要是接活,你让我干活,好,我交给幕后的类去干,你满意就成,那怎么知道被代理类能不能干呢?同根就成,大家知根知底,你 ...
- java设计模式(装饰模式)
装饰模式实现了可以动态地为原对象扩展方法 装饰对象与被装饰的都实现了同一个接口(或抽象类) 举个例子: 工作 可以边吃东西边工作,也可以边喝东西边工作,还可以工作的时候边吃边喝 创建共同接口 Work ...
- Java设计模式(7)装饰模式(Decorator模式)
Decorator常被翻译成"装饰",我觉得翻译成"油漆工"更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee.这 ...
- Java设计模式学习记录-装饰模式
前言 装饰模式也是一种结构型模式,主要是目的是相对于类与类之间的继承关系来说,使用装饰模式可以降低耦合度.JDK中有不少地方都使用到了装饰模式,例如Java的各种I/O流,javax.swing包中一 ...
- Java设计模式(十三) 别人再问你设计模式,叫他看这篇文章
原创文章,转载请务注明出处 OOP三大基本特性 封装 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的属性和方法只让可信的类操作,对不可信的进行信息隐藏. 继承 继承是指这样一种能力,它可以使 ...
- Java设计模式(10)代理模式(Proxy模式)
理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣. Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,P ...
随机推荐
- Ubuntu不卸载ibus前提下安装搜狗输入法
第一步 在命令行中输入以下行命令安装fictx框架 sudo apt-get install fcitx fcitx-config-gtk im-switch 第二步 去 http://pinyin. ...
- git revert all changes
点击打开链接https://www.kernel.org/pub/software/scm/git/docs/git-reset.html # Revert changes to modified f ...
- 01_安装redhat 7.1时常出现的问题
1. 笔记本安装时出现"dev/boot does not find ",进不去安装界面. 这是因为pci设备的问题,解决方法:在出现安装选项时,按Tab进入option模式,在末 ...
- 用javascript操作xml(三)关于Jquery的html()不兼容IE的解决办法
当 $("#xxx").html(data); 不兼容,方法替换为 document.getElementById("xxx").innerHTML=data;
- PHP获取IP地址所在的地理位置
1.http://ip.qq.com/cgi-bin/searchip?searchip1=XXX 2.http://int.dpool.sina.com.cn/iplookup/iplookup.p ...
- Mysql 与 php动态网站开发 入门教程
这个系列的教程由表单开始写,因为表单可以把数据库和web 之间的交互表现得很明显.提交表单 ,数据库记录注册信息. 本教程属于基础教程.大神请略过. 对于php和mysql之间的稳固性很 ...
- WPF窗体禁用最大化按钮
禁用WPF窗体的最大化按钮可以使用Windows API改变按钮状态的方法实现.使用GetWindowLong可以得到当前按钮的状态.使用SetWindowLong可以设置按钮的状态.使用SetWin ...
- C#中线程的用法
通过委托的方式创建线程 static int sum(int x) { return x+x; { Func<int> a = sum; 创建一个新的线程格式:a.BeginInvoke( ...
- to disable the entity lazy load, The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
The ObjectContext instance has been disposed and can no longer be used for operations that require a ...
- hdu 4445
今天模拟了一场去年金华的现场赛: 我和小珺两人出了5个题,感觉还可以: 不过这次的题目确实比较简单: 这个题目感觉不错,不难,以前见过用这种方法的,但一直没写过: 这次写下练练手: 思路,将角度分成1 ...