有时,你想要在程序运行期间为某个对象组合新的行为,且在某种情况下,你需要对象的行为发生一些细小的变化,并且这些变化可以自由组合。这时,装饰者模式就可以满足这种需求。

所谓装饰者模式,也叫修饰者模式、装饰器模式,意图是在运行时组合操作的新变化,即动态地给一个对象添加一些额外的职责。

装饰模式在中国使用的那实在是多,中国的文化是中庸文化,中国人都比较“爱面子”,说话做事呢都不能太直接,必须给对方留有余地。比如某个阳光灿烂的清晨,领导兴高采烈精神焕发地出现在你面前,你抬头一看,哎,换发型了,怎么这么挫?但是你还是会一遍又一遍地压抑自己的内心,面带微笑说,领导今天真是帅气!领导一听,哎,这个员工挺有眼光,然后春风满面扬长而去。若你不识抬举,跟领导说,你这个发型怎么这么难看,像个糟老头!我敢保证,你离辞职不远了。。。

再来说说邻居的阿姨有个女儿,名叫小红,芳龄28,生的是亭亭玉立,貌美如花,眼看着闺蜜,同学一个个结婚生子,而小红却依然孑然一身,阿姨愁得每天吃不好睡不着。然后就拖着范大妈给介绍对象,范大妈一想,哎,我刚好有个同学的儿子华哥还单着,要不给介绍给小红把,年龄大点,但是多会照顾人呢。。。

我们就来说说这个华哥,范大妈一想,可不能直接说年龄、身高、长相,那敢情小花看不上怎么办?她就寻思着多给小花说说华哥的“优异”条件,这样一修饰,华哥就是难得的”钻石王老五”啦,小花不要还有小刘呢。

范大妈简单画了个图,是这样的:

定义了男人的抽象类,然后有个普通男人实现类,再有个高学历的男人实现类,再有好工作男人实现类,再有好家境男人的实现类,看看这些类:

package com.pattern.decorator.v1;
/*** 那男人说了,把我的条件跟人家说说* 同意就交往,不行就算了,给句痛快话* @author **/
public abstract class Man {public abstract void showAppearance();//外在条件public abstract void appointment(boolean yesOrNo);//是否同意呢
}
package com.pattern.decorator.v1;
/*** 外在条件太一般了,咋整?* @author **/
public class NormalMan extends Man {@Overridepublic void showAppearance() {System.out.println("年龄40,身高1.68cm,长相一般,有点黑,好在不是歪瓜裂枣...");}@Overridepublic void appointment(boolean yesOrNo){if(yesOrNo){System.out.println("同意啦,交往吧!");}else{System.out.println("太挫了,休想!");}}
}
package com.pattern.decorator.v1;
/*** 高智商高学历,不错哦,继续看看。。。* @author **/
public class GoodEducationMan extends NormalMan {private void showEducation(){System.out.println("清华大学博士哦...");}@Override
public void showAppearance() {this.showEducation();super.showAppearance();
}
}
package com.pattern.decorator.v1;
/*** 男人40一枝花,这条件也是没谁了,老张闺女不行还设有老李家呢* @author **/
public class GoodWorkMan extends GoodEducationMan {@Override
public void showAppearance() {this.showWork();super.showAppearance();
}
private void showWork(){System.out.println("某证券公司部门经理...");}
}
package com.pattern.decorator.v1;
/*** 家境还这么好,老人无负担,谁看不上谁无脑* @author **/
public class GoodParentsMan extends GoodWorkMan{private void showParents(){System.out.println("爸妈都是公务员,拿着退休金在家乐呵呵....");}@Override
public void showAppearance() {this.showParents();super.showAppearance();
}
}

然后范大妈就跟小红说,这个男人呀,是个高材生博士,在某证券公司当老总,父母是公务员,虽然年龄稍大,长相身高都一般,那都不是事儿呀,你考虑考虑?

package com.pattern.decorator.v1;
/*** 老张闺女相亲录* @author **/
public class Test_DatingWoman {public static void main(String[] args){Man man=new GoodParentsMan();高学历 好工作 家境好 外在条件man.showAppearance();//相亲女看条件man.appointment(true);//然后觉得很开心啊,不错啊,同意同意}
}

以上是通过“继承”的方式确实解决了这个问题,但是现实的情况很复杂的,可能小红听范大妈说完学历高后,就直接乐开花了,直接同意了,后面工作好,家境好都不需要了,或者小红觉得比较在意工作,先说了工作就不用说别的了,那怎么办?继续扩展类?你能扩展多少个类?这还是一个比较简单的场景,一旦需要装饰的条件非常的多,比如20 个,你还通过继承来解决,你想想的子类有多少个?类与类之间的父子关系是怎样?你是不是马上就要崩溃了!

好,你也看到通过继承情况确实出现了问题,类爆炸,类的数量激增,光写这些类不累死你才怪,而且还要想想以后维护怎么办,谁愿意接收这么一大堆类的维护哪?并且在面向对象的设计中,如果超过2 层继承,你就应该想想是不是出设计问题了,是不是应该重新找一条道了,这是经验值,不是什么绝对的,继承层次越多你以后的维护成本越多,问题这么多,那怎么办?好办,装饰模式出场来解决这些问题,我们先来看类图:


  增加一个装饰抽象类和三个实现类,其中ManDecorator的作用是封装Man类,看源代码:

package com.pattern.decorator.v2;
/*** 邻居阿姨看了直叹气,这条件,怎么跟人家闺女说呢* 还是先把男人包装下,不能直接说,不然就泡汤了* @author **/
public abstract class ManDecorator extends Man {private Man man;public ManDecorator(Man man) {super();this.man = man;}@Overridepublic void showAppearance() {this.man.showAppearance();}@Overridepublic void appointment(boolean yesOrNo) {this.man.appointment(yesOrNo);}}
package com.pattern.decorator.v2;
/*** 高智商高学历,不错哦,继续看看。。。* @author **/
public class GoodEducationDecorator extends ManDecorator {public GoodEducationDecorator(Man man){super(man);}private void showEducation(){System.out.println("清华大学博士哦...");}@Overridepublic void showAppearance() {this.showEducation();super.showAppearance();}
}
package com.pattern.decorator.v2;
/*** 男人40一枝花,这条件也是没谁了,老张闺女不行还设有老李家呢* @author **/
public class GoodWorkDecorator extends ManDecorator {public GoodWorkDecorator(Man man) {super(man);}private void showWork(){System.out.println("某证券公司部门经理...");}@Overridepublic void showAppearance() {this.showWork();super.showAppearance();}
}
package com.pattern.decorator.v2;
/*** 家境还这么好,老人无负担,谁看不上谁无脑* @author **/
public class GoodParentsDecorator extends ManDecorator {public GoodParentsDecorator(Man man) {super(man);}private void showParents(){System.out.println("爸妈都是公务员,拿着退休金在家乐呵呵....");}@Overridepublic void showAppearance() {this.showParents();super.showAppearance();}
}

然后范大妈找到小红,就问问小红的相亲标准呀,然后根据她的品味一个条件一个条件地跟她说,直到她同意为止:

package com.pattern.decorator.v2;
/*** 老张闺女相亲录* @author **/
public class Test_DatingWoman {public static void main(String[] args){Man man=null;man=new NormalMan();//外在条件man=new GoodParentsDecorator(man);//家境好man=new GoodEducationDecorator(man);//高学历man=new GoodWorkDecorator(man);//好工作man.showAppearance();//相亲女看条件,其实家境好,学历高就暗自点头了man.appointment(true);//然后觉得很开心啊,不错啊,同意同意}
}

这就是装饰者模式,装饰者模式的通用类图如下:

看类图,Component 是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象,比如上面的相亲男,记住在装饰模式中,必然有一个被提取出来最核心、最原始、最基本的接口或抽象类,就是Component。ConcreteComponent 这个是最核心、最原始、最基本的接口或抽象类的实现,你要装饰的就是这个东西Decorator 一般是一个抽象类,做什么用呢?实现接口或者抽象方法,它里面可不一定有抽象的方法呀,在它的属性里必然有一个private 变量指向Component。ConcreteDecoratorA 和ConcreteDecoratorB 是两个具体的装饰类,你要把你最核心的、最原始的、最基本的东西装饰城啥东西,上面的例子就是把一个比较平庸的男人装饰成大家认可的成功男士。

继承和装饰者模式的区别

装饰者模式是对继承的有力补充,继承是给一个类添加行为的比较有效的途径。通过使用继承,可以使得子类在拥有自身方法的同时,还可以拥有父类的方法。但是使用继承是静态的,在编译的时候就已经决定了子类的行为,我们不便于控制增加行为的方式和时机。而装饰者模式是动态组合,组合关系的优势就在于不会破坏类的封装性,且具有较好的松耦合性,可以使系统更加容易维护。但是它的缺点就在于也要创建很多的对象。

装饰者的使用场景

  1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

  2、需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。  当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。

源码下载:http://download.csdn.net/download/pelifymeng2/9994734

Java设计模式--装饰者模式【Decorator Pattern】相关推荐

  1. java设计模式装饰者模式优点_java设计模式之--装饰者模式

    装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装 ...

  2. JAVA设计模式-装饰器模式(Decorator)

    装饰器模式(Decorator) 为了某个实现类在不修改原始类的基础上进行动态地覆盖或者增加方法 采用--------装饰器模式 实现类要保持与原有类的层级关系 装饰器模式是一种特殊的适配器模式 拿适 ...

  3. 【Java设计模式系列】装饰器模式(Decorator Pattern)

    简介 一般有两种方式可以给一个类或对象新增行为: 继承 子类在拥有自身方法同时还拥有父类方法.但这种是静态的,用户无法控制增加行为的方式和时机. 关联 将一个类的对象嵌入另一个对象,由另一个对象决定是 ...

  4. python中的装饰器、装饰器模式_python 设计模式之装饰器模式 Decorator Pattern

    #写在前面 已经有一个礼拜多没写博客了,因为沉醉在了<妙味>这部小说里,里面讲的是一个厨师苏秒的故事.现实中大部分人不会有她的天分.我喜欢她的性格:总是想着去解决问题,好像从来没有怨天尤人 ...

  5. python 设计模式之装饰器模式 Decorator Pattern

    #写在前面 已经有一个礼拜多没写博客了,因为沉醉在了<妙味>这部小说里,里面讲的是一个厨师苏秒的故事.现实中大部分人不会有她的天分.我喜欢她的性格:总是想着去解决问题,好像从来没有怨天尤人 ...

  6. 设计模式(三):“花瓶+鲜花”中的装饰者模式(Decorator Pattern)

    在前两篇博客中详细的介绍了"策略模式"和"观察者模式",今天我们就通过花瓶与鲜花的例子来类比一下"装饰模式"(Decorator Patte ...

  7. 极速理解设计模式系列:23.装饰器模式(Decorator Pattern)

    五个角色:部件(Component).具体部件(ConcreteComponent).装饰抽象类(Decorator).具体装饰对象(ConcreteDecorator).客户端(Client) 部件 ...

  8. 设计模式 -结构型模式_ 装饰者模式Decorator Pattern 在开源软件中的应用

    文章目录 定义 结构图 需求 装饰者模式 装饰者模式在MyBatis中的应用 小结 定义 装饰模式 Decorator : 在不改变原有功能的基础上, 动态的给一个对象添加一些额外的职责 ,非常符合开 ...

  9. C++实现装饰者模式Decorator Pattern

    设计原则5:类应该对扩展开放,对修改关闭. 目标:允许类容易扩展,在不修改现有代码的情况下,就可搭配新的行为. 好处:设计具有弹性可以应对改变,可以接受新的功能来应对改变的需求. 遇到的问题:类数量爆 ...

最新文章

  1. C与C++的内存机制的比较
  2. 54 Django 模型层(1) 单表查询
  3. php 关闭oracle,CSS_ORACLE启动和关闭实例,实例启动和关闭:一.数 - phpStudy
  4. [leetcode-347-Top K Frequent Elements]
  5. 从摩托罗拉、诺基亚再到航空领域应用,这款开源数据库的成功如何成就天才程序员?...
  6. LoadRunner 11简单使用
  7. 2015计算机二级office真题,2015计算机二级office题库(含答案)
  8. c++ primer 5学习小结
  9. 插值法(三次样条插值)
  10. C6678多核DSP——CMD文件介绍
  11. JAVA经典算法40题(供面试所用)
  12. Q版京剧脸谱来喽——小生
  13. leetcode之Isomorphic strings
  14. ftrack与Adobe家三剑客!
  15. 课堂笔记:Android UI控件
  16. NLP-阅读理解-2015:MRC模型-指导机器去阅读并理解【开篇之作】【完形填空任务】【第一次构建大批量有监督机器阅读理解训练语料】【三种模型结构:LSTM、Attention、Impatient】
  17. 2个小巧好用的文本编辑器--Cuda Text(及中文设置方法)与Nopad--
  18. 解决Spring Spring Data JPA 错误: Page 1 of 1 containing UNKNOWN instances
  19. 因为我懒,所以选择数学
  20. Apprentice: Using Knowledge Distillation Techniques To Improve Low-Precision Network Accuracy

热门文章

  1. Thymeleaf简要介绍
  2. cesium之3D tiles格式介绍
  3. CSS3中的calc()函数以及在less中的使用
  4. 免费好用无广告的开源 gif制作软件 screentogif
  5. 整合网络时间同步系统(NTP时钟同步设备)解决方案
  6. 脑子嗡嗡记不住该怎么办
  7. python中有序数据类型_Python的数据类型总结
  8. Windows停止端口运行的进程
  9. 荷兰海牙旅游景点,让你领略欧洲的美丽风光
  10. 【漏洞利用总结与解决方案】