Decorator Pattern装饰模式

  • 细说装饰模式
    • 细说装饰模式
      • 定义
      • UML模型
      • 场景
        • 场景一
        • 场景二
      • 代码
        • 代码一
        • 代码二
        • 基于UML的代码
      • 装饰模式应用和注意事项

细说装饰模式

提示:
博主:章飞 _906285288的博客
博客地址:http://blog.csdn.net/qq_29924041


细说装饰模式

装饰模式在java或者在android中的应用非常广泛,如果细细的去品味下源码的话,里面真的是太多场景使用的都是装饰模式,下面就针对这个简单讲一下什么是装饰模式,装饰模式也是一种相对比较稍微难一点点的设计模式

定义

装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
举个例子,我记得小时候上小学的时候,我们那个年代的小学生,都有一个爱书的好习惯,每当开学领书回去的时候,都要从小店买几张包书皮,然后回家把语文数学什么的课本都被包装一下,这种其实就是装饰模式。或者包装模式,给书包了层书皮

UML模型


从图上可以看到,在装饰模式中主要分为以下几个角色:
1:Component 是一个接口或者抽象类,是我们需要包装的原始对象,类似上面的书籍

2:Decorator 抽象装饰类是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类拓展该方法,以达到装饰的目的。可以是抽象类或者接口,实现了Component接口

3:Concreate Component 最核心,最基本的,接口或者抽象类的实现 数学课本

4:ConcreteDecorator 具体装饰类是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法以便扩充对象的行为,

场景

场景一

场景来自设计模式之禅。上过学的同学应该都知道,每年都有期中和期末考试吧,可以回想一下,期中考试考完了,成绩下来了。然后老师给了大家一份各个科目的成绩单让家长看,看完成绩之后,然后签字带回来,试想一下。如果你是班级中上游的话,但是某科目成绩整体都比较低,而你也比较低的时候,如果只是拿分数回去给家长看,家长一定会斥责为什么考那么低对吧。那肯定签字会遇到麻烦啊。如果某科目分数很低,而你已经排名很高了。如果换种方式给家长可能会更好一点,这个时候,如果你把某科目的总分数,或者某科目在班级的总排名告诉爹妈,顺便再加一下分数的话。是不是起到意想不到的效果呢??这就是装饰者模式。我们需要在原始成绩单的基础上,稍微加一点装饰,让父母看到我想给父母看到的那部分,而弱化本来的分数。

场景二

这是目前比较流行的案例。咖啡类型案例。星巴克提供不同种类的咖啡和咖啡的调料,星巴克需要一些类来描述他们并且能计算出任意一种咖啡和任意几种调料搭配在一起的价格,如果我们用继承为每一种搭配写一个类的话,我们就需要把所有的咖啡全部穷举出来,想想星巴克的咖啡种类,没有上百种,那也有几十种类啊。想想都心累。
如果去套用装饰者模式,抽象出基类Beverage作为饮料类,而添加物作为装饰类,通过添加物添加,然后装饰出不同种类的咖啡。这样也就避免了类的爆炸的情况
Beverage(饮料类):相当与Component
HouseBlend、DarkRoast…(混合咖啡类、礁炒咖啡类…):相当于ConcreteComponent
CondimentDecorator(调料装饰者类):相当于Decorator
Milk、Mocha…(牛奶类、摩卡类…):相当于ConcreteDecorator
装饰者模式的特点,一个ConcreteComponent可以被任意个ConcreteDecorator装饰。
结合实例就来解释,一种咖啡可以和任意种调料搭配。
这样我们来应对各种点单的搭配的时候只需要在一种咖啡(ConcreteComponent)加上各种(ConcreteDecorator)就可以完成了,是不是觉得特别方便。

代码

代码一

package src.com.zzf.designpattern.decoratorpattern.demo1;/*** * @author Administrator*  装饰者模式中具体的componnet部分,即需要装饰的类的顶层抽象类,*学校的成绩单*/
public abstract class SchoolReport {//报告成绩public abstract void report();//签字public abstract void sign(String name);
}
package src.com.zzf.designpattern.decoratorpattern.demo1;/*** 装饰者模式中具体的实现类,即需要装饰的具体对象* @author Administrator**/
public class FouthGradSchoolReport extends SchoolReport{@Overridepublic void report() {// TODO Auto-generated method stubSystem.out.println("尊敬的XXX家长:");System.out.println(" ......");System.out.println(" 语文 62 数学65 体育 98 自然 63");System.out.println(" .......");System.out.println(" 家长签名: ");}@Overridepublic void sign(String name) {// TODO Auto-generated method stubSystem.out.println("家长签名为:"+name);}}

对成绩单进行装饰的顶层的抽象类

package src.com.zzf.designpattern.decoratorpattern.demo1;public abstract class Decorator extends SchoolReport{private SchoolReport mSchoolReport;public Decorator(SchoolReport mSchoolReport){this.mSchoolReport = mSchoolReport;}@Overridepublic void report() {// TODO Auto-generated method stubthis.mSchoolReport.report();}@Overridepublic void sign(String name) {// TODO Auto-generated method stubthis.mSchoolReport.sign(name);}}

最高分的装饰类

package src.com.zzf.designpattern.decoratorpattern.demo1;public class HighScoreDecorator extends Decorator {public HighScoreDecorator(SchoolReport mSchoolReport) {super(mSchoolReport);// TODO Auto-generated constructor stub}private void reportHighScore() {System.out.println("这次考试语文最高是75,数学是78,自然是80");}@Overridepublic void report() {// TODO Auto-generated method stubthis.reportHighScore();super.report();}public void onCreate(){}}

排名的装饰类

package src.com.zzf.designpattern.decoratorpattern.demo1;public class SortDecorator extends Decorator {public SortDecorator(SchoolReport mSchoolReport) {super(mSchoolReport);// TODO Auto-generated constructor stub}//告诉老爸学校的排名情况private void reportSort(){System.out.println("我是排名第38名...");}@Overridepublic void report() {// TODO Auto-generated method stubsuper.report();this.reportSort();}
}

对成绩单的美化后的成绩单

package src.com.zzf.designpattern.decoratorpattern.demo1;public class SugarFouthGradSchoolReport extends FouthGradSchoolReport{private void reportHighScore(){System.out.println("这次考试语文38分,英语80分");}private void reportSort(){System.out.println("汇报排名为38名");}@Overridepublic void report() {// TODO Auto-generated method stubthis.reportHighScore();super.report();this.reportSort();}
}

测试类

package src.com.zzf.designpattern.decoratorpattern.demo1;/*** 装饰者模式是一种相对比较复杂的* 角色:* Componnet:要装饰的抽象出来的类* ConcreteComponnet:具体的要装饰的物品* Decorater:装饰者,需要继承要装饰的抽象类* ConcreteDecoraterA:装饰形式A* ConcreteDecoraterB:装饰形式B* * @author Administrator** 通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,* 那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的*** 装饰者与被装饰者拥有共同的超类,继承的目的是继承类型,而不是行为*/
public class Father {public static void main(String[] args) {
//      SchoolReport mSchoolReport = new SugarFouthGradSchoolReport(); //通过继承的形式扩展,可能会最终导致类过多,维护成本高
//      一般情况下类的继承尽量低于3个
//      mSchoolReport.report();
//      mSchoolReport.sign("签个锤子");SchoolReport mSchoolReport = new FouthGradSchoolReport();System.out.println("1:"+mSchoolReport.toString());mSchoolReport = new HighScoreDecorator(mSchoolReport);System.out.println("2:"+mSchoolReport.toString());mSchoolReport.report();mSchoolReport = new SortDecorator(mSchoolReport);System.out.println("3:"+mSchoolReport.toString());mSchoolReport.report();}
}

代码二

package src.com.zzf.designpattern.decoratorpattern.demo3;/*** 抽象的被装饰对象,即咖啡类,相当于Component* @author zhouzhangfei**/
public abstract class Coffee {protected String description="";public String getDescription(){return description;}public abstract double cost();
}
package src.com.zzf.designpattern.decoratorpattern.demo3;/*** 抽象的装饰者,即去装饰咖啡对象,相当于Decorator* @author zhouzhangfei**/
public abstract class CondimentDecorator extends Coffee{public abstract String getDescription();}
package src.com.zzf.designpattern.decoratorpattern.demo3;/*** 具体需要装饰的咖啡类别1,ConcreteComponent* @author zhouzhangfei**/
public class DarkRoastCaffee extends Coffee {public DarkRoastCaffee(){description="Dark Roast coffee";}@Overridepublic double cost() {// TODO Auto-generated method stubreturn 3;}}
package src.com.zzf.designpattern.decoratorpattern.demo3;/*** 具体的咖啡类别2,相当于ConcreteComponent* @author zhouzhangfei**/
public class HouseBlendCoffee extends Coffee{public HouseBlendCoffee(){description="House Blend coffee";}@Overridepublic double cost() {return 4.9;}
}
package src.com.zzf.designpattern.decoratorpattern.demo3;/*** 咖啡的添加物1,类比于ConcreteDecorator* @author zhouzhangfei**/public class Milk extends CondimentDecorator {protected Coffee beverage;public Milk(Coffee beverage){this.beverage=beverage;}@Overridepublic String getDescription() {return beverage.getDescription()+",with milk";}@Overridepublic double cost() {return 2.3+beverage.cost();}}
package src.com.zzf.designpattern.decoratorpattern.demo3;/*** 咖啡的添加物1,类比于ConcreteDecorator* @author zhouzhangfei**/
public class Mocha extends CondimentDecorator {protected Coffee beverage;public Mocha(Coffee beverage){this.beverage=beverage;}@Overridepublic String getDescription() {return beverage.getDescription()+",with Mocha";}@Overridepublic double cost() {return 1.2+beverage.cost();}}
package src.com.zzf.designpattern.decoratorpattern.demo3;public class Starbucks {public static void main(String[] args) {Coffee  coffee1 = new HouseBlendCoffee();Milk milk = new Milk(coffee1);System.out.println(milk.getDescription()+"\t"+milk.cost());Coffee  coffee2 = new HouseBlendCoffee();Milk milk2 = new Milk(coffee1);System.out.println(milk2.getDescription()+"\t"+milk2.cost());}
}

基于UML的代码

package src.com.zzf.designpattern.decoratorpattern.demo2;public abstract class Component {public abstract void operate();
}
package src.com.zzf.designpattern.decoratorpattern.demo2;public class ConcreteComponent extends Component {@Overridepublic void operate() {// TODO Auto-generated method stubSystem.out.println("ConcreteComponet operate");}}
package src.com.zzf.designpattern.decoratorpattern.demo2;public class Decorator extends Component{Component mComponent;public Decorator(Component mComponent){this.mComponent = mComponent;}@Overridepublic void operate() {// TODO Auto-generated method stubmComponent.operate();}}
package src.com.zzf.designpattern.decoratorpattern.demo2;public class ConcreteDecorator extends Decorator{public ConcreteDecorator(Component mComponent) {super(mComponent);// TODO Auto-generated constructor stub}private void operateB() {System.out.println("ConcreteDecorator operateB");}@Overridepublic void operate() {// TODO Auto-generated method stubsuper.operate();operateB();}}
package src.com.zzf.designpattern.decoratorpattern.demo2;public class ConcreteDecorateA extends Decorator{public ConcreteDecorateA(Component mComponent) {super(mComponent);// TODO Auto-generated constructor stub}private void operateA(){System.out.println("ConcreteDecorateA operateA");}@Overridepublic void operate() {// TODO Auto-generated method stuboperateA();super.operate();}}

测试类:

package src.com.zzf.designpattern.decoratorpattern.demo2;public class Test {public static void main(String[] args) {Component mComponent = new ConcreteComponent();mComponent = new ConcreteDecorateA(mComponent);mComponent = new ConcreteDecorator(mComponent);mComponent.operate();}
}

装饰模式应用和注意事项

1:装饰者模式中用到了继承,但是这里装饰者模式用继承是为了保证装饰者和被装饰者有共同的超类,而不是为了给被装饰的类扩展新的特性,而装饰者模式中新的特性是通过类与类的组合(has-a的关系)而得到的,所以把装饰者模式和继承看做同一类设计思想是不恰当的。

2当你的有些设计是针对某些具体的Component类型即ConcreteComponent时,装饰者模式是不适用的,因为被装饰过的类是通过组合来实现特性的扩展,所以装饰过的类并不具有某个特定的ConcreteComponent类型,而只具有其本身的类型和它继承的Decorator以及Component的类型,所以只有当你的操作都是针对Component类型的时候,装饰者模式才是合适的,否则你就要重新考虑你的设计。

3:会引入大量的类,常常让人觉得不知所措,特别是对于初学者来说,最好的例子就是java的I/O类以及android 中的Context关系类,大量的类并不会影响其实一个好用的设计模式


欢迎继续访问,我的博客

【设计模式十六之装饰模式】装饰者模式相关推荐

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

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

  2. 对设计模式的总结之装饰模式与代理模式

    前言 面向对象编程追求的本质-提高扩展性.可维护性.灵活性和复用性.合理利用面向对象6个原则,能够很好的达到要求.如何利用好就是至关重要的了,前人总结了23+个设计模式能够让初学者更容易学到其中的精髓 ...

  3. Java设计模式之结构型:装饰器模式

    一.什么是装饰器模式: 当需要对类的功能进行拓展时,一般可以使用继承,但如果需要拓展的功能种类很繁多,那势必会生成很多子类,增加系统的复杂性,并且使用继承实现功能拓展时,我们必须能够预见这些拓展功能, ...

  4. 大聪明教你学Java设计模式 | 第七篇:装饰器模式

    前言 大聪明在写代码的过程中发现设计模式的影子是无处不在,设计模式也是软件开发人员在软件开发过程中面临的一般问题的解决方案.大聪明本着"独乐乐不如众乐乐"的宗旨与大家分享一下设计模 ...

  5. HTML5游戏引擎(十六)-屏幕适配——showAll模式 noScale模式 noBorder模式 exactFit模式 fixedWidth模式 fixedHeight模式

    HTML5游戏引擎(十六)-屏幕适配--showAll模式 & noScale模式 & noBorder模式 & exactFit模式 & fixedWidth模式 & ...

  6. 设计模式解密(9)- 装饰者模式

    1.简介 定义:装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象. 拆分定义,总结特点:   1.不改变原类文件. 2.不 ...

  7. 设计模式(二)(装饰者模式、工厂方法模式、抽象工厂模式)

    三:装饰者模式 装饰者模式动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. 意图:动态地给一个对象添加一些额外的职责.就增加功能来说,装饰器模式相比生成子类更为灵活. 主 ...

  8. 设计模式 ( 十六 ) 观察者模式Observer(对象行为型)

    设计模式 ( 十五 ) 观察者模式Observer(对象行为型) 1.概述 一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力.当对象们连接在一起时,它们就可以相互提供服务和信息. 通常来 ...

  9. 设计模式学习(三)——装饰器模式

    前言 距离上一次正儿八经地写随笔已经有一段时间了,虽然2月10号有一篇关于泛型的小记,但是其实只是简单地将自己的学习代码贴上来,为了方便后续使用时查阅,并没有多少文字和理解感悟.之所以在今天觉得有必要 ...

最新文章

  1. C#访问MySQL数据库的方法
  2. POJ - 2676 Sudoku(dfs)
  3. 玩转12306之系统登录
  4. Python编程基础21:GUI编程
  5. ARM架构、指令集、内核版本、CISC与RISC、ARM产品线
  6. css中的大于号是什么意思 有何作用
  7. Centos Nginx+PHP Install 史上最完美
  8. oracle-关于分组函数的小细节
  9. Java 32位最新版 (Java SE 8)
  10. spyder python_spyder python2.7下载
  11. rapidminer java_在Java应用程序RapidMiner的整合(Integration of RapidMiner i
  12. TFS2010 - 强制撤销签出
  13. 2022edu教育邮箱哪个好?申请注册教育邮箱很难吗?
  14. adb命令操作安卓hosts文件
  15. 期货量化交易matlab,【策略分享】Matlab量化交易策略源码分享
  16. 移动mm 话费支付接入过程(ane)
  17. java查找算法:线性查找
  18. 【RQNOJ】460 诺诺的队列
  19. pyQt5 帮助手册的使用
  20. 2048网页版html项目报告,jQuery编写网页版2048小游戏

热门文章

  1. 恒星物联-排水管网水质监测系统方案 管网水质监测
  2. 随笔-在Unity3d中模拟键盘按键
  3. 蓝桥杯1——李白打酒加强版
  4. 转载-CentOS虚拟机和物理机共享文件夹实现
  5. MathJax笔记-精简打印版
  6. 【最经典的79个】软件测试面试题(内含答案)提前备战“金九银十”
  7. isempty()函数用法
  8. 【html】关于doctype
  9. C#大作业——人事管理系统
  10. 印度尼西亚 east java_东爪哇(EAST JAVA)