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 ...
随机推荐
- Java并发编程二三事
Java并发编程二三事 转自我的Github 近日重新翻了一下<Java Concurrency in Practice>故以此文记之. 我觉得Java的并发可以从下面三个点去理解: * ...
- 4MLinux7.0 服务器配置详解 别名TheSSS
TheSSS download 特性:thttp,php5.5.1,mysql,vsftp,proxy,firewall,带rpm管理器.更新频繁. 官方帮助文件:View (新窗口打开) 发现国内4 ...
- jquery的return this.each()的作用
经常看到在运用jquery插件绑定事件时候,都会用到each. 下面来比较下使用return this和return this.each()在使用的区别. 注意:使用each的时候引用this,必须使 ...
- vagrant 设置除默认工项目之外的synced_folder一个坑
vagrant和host共享的目录,模式是以host主机目录为主,vagrant目录为从,所以记住当你新建同步目录的时候一定要先把vagratn目录文件备份一下,不然会被host目录覆盖
- JBPM4 常用表结构及其说明
本文从表结构.操作时表的变化以及jbpm4.4各个包的作用来介绍jbpm的. 第一部分:表结构说明 Jbpm4 共有18张表,如下,其中红色的表为经常使用的表 一:资源库与运行时表结构 1. J ...
- 监听div内容改变
做前端突击队,外星人那道是自己手动模拟那个时间的变化的,但正确思路应该是监听div内容的变化然后同步到输入框中,遂今天找了一下,结果如下: $('div').bind('DOMNodeInserted ...
- load-store/register-memory/register-plus-memory比较
在理解ARM的load-store架构时,我在百度上搜索了很长时间,但是始终找不到一篇像样的中文文章.最后,在用谷歌搜索的英文网站上终于找到了一些蛛丝马迹.让我们先看一下一篇英文资料. Process ...
- POJ 2252 Dungeon Master 三维水bfs
题目: http://poj.org/problem?id=2251 #include <stdio.h> #include <string.h> #include <q ...
- pyramid的第一个项目
1,安装pyramid --在次之前最好先安装python virtualenv --python virtualenv ---激活方式pyenv activate pip install pyram ...
- 分页加查询的sql语句
"SELECT TOP(@pagesize) * FROM T_News WHERE(NewsTitle LIKE @newskey OR NewsContent LIKE @newskey ...