本文由码农网 – 鲁阿皓原创,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划

前情提要:http://blog.csdn.net/baidu_30889437/article/details/50917814

JVM:”上次给我招的工人不错啊!”

oo程序员:”………..”

JVM:”现在来我开的博物馆生意越来越好了,原来”舞台剧”的方式已经不能满足顾客的需求了”

oo程序员:”………..”

JVM:”我决定要换一种运营模式,把每个演播厅都租出去,让那些想表演节目的对象们来租演播厅和相关器械,这样我就能坐地收钱了!”

oo程序员:”………..”

JVM:”合伙干吧?怎么样?你三我七!”

oo程序员:”………..”

JVM:”四六?”

oo程序员:”成交!先说说需求。”

JVM:”首先有不同类型的演播厅和不同的装饰品/器械,每种物品都要付一定的租金,你要做的就是一件事,把总租金(演播厅+饰品/器械)算出来。”

oo程序员:”把价格表给我!”

  1. 卡通演播厅(CartoonStudio 100
  2.  
  3. 小丑演播厅(JokerStudio 150
  4.  
  5. 超级演播厅(SuperStudio 300
  6.  
  7. 气球(Balloon 10
  8.  
  9. 灯光(Lamplight 25
  10.  
  11. 麦克风(Microphone 20

最后还写下了这个:

  1. public abstract class Anything_ex()
  2. {
  3. String description=" ";
  4. public String getDescription()
  5. {
  6. return description;
  7. }
  8. public abstract int cost();
  9. }

仔细一想也对,无论是演播厅还是装饰品,都需要描述(description)和cost(价格),写一个共同的父类无可厚非。

接着写下你设计的第一个类:

  1. class CartoonandBalloon extends Anything_ex
  2. {
  3. ....
  4. public int cost()
  5. {
  6. return 100+10;
  7. }
  8. } //带气球的卡通演播厅

第二个:

  1. class CartoonandLamplight extends Anything_ex
  2. {
  3. ...
  4. public int cost()
  5. {
  6. return 100+25;
  7. }
  8. } //带灯光的卡通演播厅

第三个:
。。。。。

没有第三个了!这样写下去可是无穷无尽的!没办法,换个思路。

在演播厅里,无论什么装饰品都有可能出现,可以把演播厅+饰品看成一个整体,通过饰品相应的has和set来控制饰品,这样的话,设计出来的类如下:

  1. class CartoonStudio extends Anything_ex
  2. {
  3. private boolean Balloon=false;
  4. .... //省略其他变量,这里只以气球为例
  5. public boolean hasBalloon()
  6. {
  7. return Ballon;
  8. }
  9. public void setBallon()
  10. {
  11. Balloon=true;
  12. }
  13. .......//省略其他has/set方法
  14. public int cost()
  15. {
  16. int cost=100; //卡通演播厅的初始价格为100
  17. if(hasBalloon)
  18. {
  19. cost+=10;
  20. }
  21. else if(hasXXX).....//省略类推下来的代码
  22.  
  23. return cost;
  24. }
  25.  
  26. }

这个看起来好多了,不用写大爆炸数量的类,虽然类写起来又臭(无数的has/set)又长(的确很长)。。。。。

但是有没有更好的方案?

答案当然是有的,不过我们必须先明确一下,上述设计的缺点。

  • 1.臭
  • 2.长
  • 3.当饰品的租金改变的时候,必须修改所有演播厅的代码(cost部分),我们当然不想这样,我们想尽可能的少修改代码(松耦合)。
  • 4.没有面对超类/接口编程。
  • 5.没有将变化的部分独立开。
  • 6.组合可能是更好的解决方案。

下面让我们看看。装饰者模式是如何解决上面问题的。

装饰者模式:动态的将责任加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

首先,我们先将演播厅和他的装饰者们分开,让装饰者继承另一个类:

  1. public abstract class Decorater_ex extends Anyting_ex
  2. {
  3. public abstract String getDescription();
  4. }

让装饰者子类重新实现getDescription()即可。

现在我们的思路是:用装饰者装饰演播厅,例如,一个带麦克风和气球的卡通演播厅,就先让气球装饰卡通演播厅,再让麦克风装饰“带气球的卡通演播厅”

先让我们分别实现这3个类:

卡通演播厅:

  1. class CortoonStudio extends Anything_ex
  2. {
  3. public CortoonStudio()
  4. {
  5. description="CortonStudio";
  6. }
  7. publuc int cost()
  8. {
  9. return 100;
  10. }
  11. }

麦克风:

  1. class Microphone extends Decorater_ex
  2. {
  3. private Anything_ex studio;
  4. public Microphone(Anything_ex studio )
  5. {
  6. this.studio=studio;
  7. }
  8. public String getDescription()
  9. {
  10. return studio.getDescription()+",Microphone"
  11. }
  12. public int cost()
  13. {
  14. return studio.cost()+20;
  15. }
  16. }

气球:

  1. class Balloon extends Decorater_ex
  2. {
  3. private Anything_ex studio;
  4. public Balloon(Anything_ex studio )
  5. {
  6. this.studio=studio;
  7. }
  8. public String getDescription()
  9. {
  10. return studio.getDescription()+",Balloon";
  11. }
  12. public int cost()
  13. {
  14. return studio.cost()+10 ;
  15. }
  16. }

代码:

  1. Anything_ex CortoonStudio =new CortoonStudio(); //一个卡通演播厅对象
  2. CortoonStudio=new Microphone(CortoonStudio); //拿麦克风装饰
  3. CortoonStudio=new Balloon(CortoonStudio); //拿气球装饰
  4. System.out.println(CortoonStudio.getDescription()+"="+CortoonStudio.cost());

输出结果:

  1. CortonStudio,Microphone,Balloon=130

结果是正确的。

这样写很好的解决了上面的问题。

  • 1.运用组合进行扩展,使当价格改变的时候,只需要修改本身的代码。
  • 2.面对超类/接口编程,使饰品增加种类的时候,并不需要修改被装饰者的代码。
  • 3.开放——关闭原则 :代码应该对扩展开放,对修改关闭。

缺陷:

  • 1.子类繁多,影响理解代码(java I/O就是装饰者模式哦。。。)。
  • 2.无法应用于需要具体类的场景。

这篇文章到此差不多结束了,作者功力尚浅,文章如有不正之处请读者指出,海涵。

Java设计模式之装饰模式趣谈的更多相关文章

  1. java设计模式学习笔记--浅谈设计模式

    设计模式的目的 编写软件的过程中,程序员面临着来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战.设计模式为了让程序具有更好的 1.代码重用性(即:相同功能的代码,不用多次编写) ...

  2. java设计模式之装饰模式

    发现设计模式的学习越来越让自己学习的东西太少了,应该多接触一些东西,多出去走一走. 装饰模式概念: 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活(大话设计模式) 在不 ...

  3. Java——设计模式(装饰模式_IO)

     /* * 装饰设计模式: *  对一组对象的功能进行增强时,就可以使用该模式进行问题的解决; * 装饰和继承都能实现一样的特点:  就是进行功能的扩转增强. * */ public class  ...

  4. JAVA设计模式:装饰模式

    前面我们学习了代理模式: 代理模式主要使用了java的多态,干活的是被代理类,代理类主要是接活,你让我干活,好,我交给幕后的类去干,你满意就成,那怎么知道被代理类能不能干呢?同根就成,大家知根知底,你 ...

  5. java设计模式(装饰模式)

    装饰模式实现了可以动态地为原对象扩展方法 装饰对象与被装饰的都实现了同一个接口(或抽象类) 举个例子: 工作 可以边吃东西边工作,也可以边喝东西边工作,还可以工作的时候边吃边喝 创建共同接口 Work ...

  6. Java设计模式(7)装饰模式(Decorator模式)

    Decorator常被翻译成"装饰",我觉得翻译成"油漆工"更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee.这 ...

  7. Java设计模式学习记录-装饰模式

    前言 装饰模式也是一种结构型模式,主要是目的是相对于类与类之间的继承关系来说,使用装饰模式可以降低耦合度.JDK中有不少地方都使用到了装饰模式,例如Java的各种I/O流,javax.swing包中一 ...

  8. Java设计模式(十三) 别人再问你设计模式,叫他看这篇文章

    原创文章,转载请务注明出处 OOP三大基本特性 封装 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的属性和方法只让可信的类操作,对不可信的进行信息隐藏. 继承 继承是指这样一种能力,它可以使 ...

  9. Java设计模式(10)代理模式(Proxy模式)

    理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣. Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,P ...

随机推荐

  1. centos 6.5 安装jenkins

    Installation sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.rep ...

  2. 配置trac

    1. enable apache mod_auth_digest 2. 设置Location

  3. jquery-ui-datepicker定制化,汉化,因手机布局美观化源码修改

    感谢浏览,欢迎交流=.= 公司微信网页需要使用日历控件,想到jquery-mobile,但是css影响页面布局,放弃后使用jquery-ui-datepicker. 话不多说,进入正题: 1.jque ...

  4. Android学习5—布局简介

    Android界面的布局主要有四种,分别为RelativeLayout.LinearLayout.TableLayout.FrameLayout,接下来分别介绍这些布局如何使用(为了简单起见,接下来的 ...

  5. 《APUE》第三章笔记(3)

    文件共享 UNIX系统支持在不同进程中共享打开的文件,首先先用一幅apue的图来介绍一下内核用于I/O文件的数据结构: 如图所见,一个进程都会有一个记录项,记录项中包含有一张打开文件描述符表,每个描述 ...

  6. 转: Android异步加载图像小结

    转:http://blog.csdn.net/sgl870927/article/details/6285535 研究了android从网络上异步加载图像,现总结如下: (1)由于android UI ...

  7. 直接通过curl方式取得数据、模拟登陆、POST数据

    博客园的Markdown编辑器太坑爹了@!!! 算了.不用格式了!!! /********************** curl 系列 ***********************/ //直接通过c ...

  8. wpf:DataGrid使用

    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" ...

  9. App 性能分析

    关键因素: ---- Instrument 性能分析神器 1. 启动时间 应用启动时间长短对用户第一次体验至关重要,同时系统对应用的启动.恢复等状态的运行时间也有严格的要求,在应用超时的情况下系统会直 ...

  10. 文件操作 - NSFileManager

    iOS的沙盒机制,应用只能访问自己应用目录下的文件.iOS不像android,没有SD卡概念,不能直接访问图像.视频等内容.iOS应用产生的内容,如图像.文件.缓存内容等都必须存储在自己的沙盒内.默认 ...