• 装饰设计模式:又名包装模式(Wrapper),以对客户端透明的方式扩展对象的功能,是继承关系的一种替代关系。装饰模式以对客户端透明的方式动态的给一个对象附加上更多的责任。换言之,客户端不会觉得在装饰前和装饰后有什么不同。
  • 下面看装饰设计模式的UML类图:

    

  • 在装饰模式中的各个角色:
  1. 抽象构件Component:给出一个抽象接口,以规范准备接收附加责任的对象。
  2. 具体构件角色:ConcreteComponent:定义一个要接收附加责任的类。
  3. 装饰角色:Decorator,实现抽象构件的接口,拥有一个抽象构件Component类型的属性,和持有抽象构件Component的对象的实例。
  4. 具体装饰:ConcreteDecoratorA,ConcreteDecoratorB:负责给具体构件对象“贴上”附加的责任。
  • 代码实现

抽象构件:

package com.lp.ecjtu.patten.decorator;public interface Component {public void Operation();
}

具体构件:

package com.lp.ecjtu.patten.decorator;public class ConcreteComponent implements Component {@Overridepublic void Operation() {//写相关的业务代码
    }
}

装饰类:

package com.lp.ecjtu.patten.decorator;public class Decorator implements Component{//体现了聚合关系,Decorator是整体,Component部分,Decorator由Component聚合而成private Component component;//数据类型为Component的属性public Decorator(Component component){//构造方法传入Component组件this.component = component;}public Decorator(){}@Overridepublic void Operation() {// TODO Auto-generated method stubcomponent.Operation();//增强功能
    }}

具体装饰角色:

package com.lp.ecjtu.patten.decorator;public class ConcreteDecoratorA extends Decorator {@Overridepublic void Operation() {// TODO Auto-generated method stubsuper.Operation();}
}package com.lp.ecjtu.patten.decorator;public class ConcreteDecoratorB extends Decorator {@Overridepublic void Operation() {// TODO Auto-generated method stubsuper.Operation();}
}

  • 装饰设计模式的应用:程序员写代码,程序员除了写代码的职责,还需要其他的责任才能完成整个项目。
package com.lp.ecjtu.patten.decorator1;
/*** 抽象构件* @author Administrator**/
public interface Person {public void coding();
}

package com.lp.ecjtu.patten.decorator1;
/*** 具体提构件类,要接收附加责任的类,程序员* @author Administrator**/
public class Employee implements Person {@Overridepublic void coding() {System.out.println("程序员加班写程序,写程序啊,最终写完了项目。。。。");}}

package com.lp.ecjtu.patten.decorator1;
/*** 装饰类* @author Administrator**/
public class Decorator implements Person{private Person Person;public Decorator(Person Person){}@Overridepublic void coding() {Person.coding();}}

package com.lp.ecjtu.patten.decorator1;
/*** 具体装饰类,项目经理A职责* @author Administrator**/
public class ManagerDecoratorA extends Decorator{private Person person;public ManagerDecoratorA(Person person) {super(person);this.person = person;}@Overridepublic void coding() {//增强父类coding方法的功能
        doEarlyWork();person.coding();}private void doEarlyWork() {System.out.println("项目经理A做需求分析");System.out.println("项目经理A做架构设计");System.out.println("项目经理A做详细设计");}}

package com.lp.ecjtu.patten.decorator1;
/*** 具体装饰类,项目经理B* @author Administrator**/
public class ManagerDecoratorB extends Decorator{private Person person;public ManagerDecoratorB(Person person) {super(person);this.person = person;}@Overridepublic void coding() {//增强父类coding方法的功能
        doEndWork();person.coding();}private void doEndWork() {System.out.println("项目经理B做首尾工作");}}

package com.lp.ecjtu.patten.decorator1;public class Client {/*** @param args*/public static void main(String[] args) {
//        Person employee = new Employee();//要接收户责任的对象(具体构件)
//        Person managerB = new ManagerDecoratorB(employee);//赋予程序员项目经理B的责任
//        Person managerA = new ManagerDecoratorA(managerB);//赋予程序员项目经理A的责任new ManagerDecoratorA(new ManagerDecoratorB(new Employee())).coding();;//managerA.coding();
        }}

运行结果:

项目经理A做需求分析
项目经理A做架构设计
项目经理A做详细设计
项目经理B做首尾工作
程序员加班写程序,写程序啊,最终写完了项目。。。。

分析:系统把人类Person从一个程序员Employee装饰成了项目经理B(把项目经理B的功能加到程序员身上),然后把项目经理B装饰成了项目经理A(把项目经理A的责任加到程序员+项目经理B的身上)。

如下图所示:

  • 装饰模式的透明性理解:装饰模式对客户端的透明性要求程序不要声明一个ConcreteComponent(程序员)类型的变量,而要声明Component(person人类)的变量。用上面的例子理解就是必须把所人类(person)的所有装饰变化,都当做人类(person)来对待,如果把人类变化成的项目经理A当成项目经理A,那就不透明了,因为不管是项目经理A,B,还是程序员都是人类。
  • 也就是说

Person employee = new Employee();//多态的方式

Person managerB = new ManagerDecoratorB(employee);

   这样是对的。如果是下面的:

Employee  employee  = new Employee();

ManagerDecoratorB managerB  = new ManagerDecoratorB(employee);

就不对了

  • 装饰设计模式的优点与缺点:
  • 优点:
  1. 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。装饰模式在系统运行期动态的决定给装饰的对象动态的“贴上”一个需要的“装饰”或者除掉一个不需要的“装饰”。继承则不同,继承关系式静态的,它在系统运行前就决定了。
  2. 通过使用不同的具体装饰类(ManagerDecoratorA,ManagerDecoratorB,C。。。。。),以及这些装饰类的排列组合,设计师么可以设计出很多不同的行为组合。(ManagerDecoratorB装饰ManagerDecoratorA,或者用ManagerDecoratorA装饰ManagerDecoratorB)
  • 缺点:
  1. 使用装饰模式会产生比使用继承关系更多的对象,更多的对象使得查错变得困难,特别是这些对象看上去都很像。装饰模式比继承产生更少的类。
  • 设计模式在JAVA I/O库中的应用

  装饰模式在Java语言中的最著名的应用莫过于Java I/O标准库的设计了。

  由于Java I/O库需要很多功能的各种组合,如果这些功能都是用继承的方法实现的,那么每一种组合都需要一个类,这样就会造成大量功能重复的类出现。而如果采用装饰模式,那么类的数目就会大大减少,功能的重复也可以减至最少。因此装饰模式是Java I/O库的基本模式。

  Java I/O库的对象结构图如下,由于Java I/O的对象众多,因此只画出InputStream的部分。

 

 

根据上图可以看出:

  ●  抽象构件(Component)角色:由InputStream扮演。这是一个抽象类,为各种子类型提供统一的接口。

  ●  具体构件(ConcreteComponent)角色:由ByteArrayInputStream、FileInputStream、PipedInputStream、StringBufferInputStream等类扮演。它们实现了抽象构件角色所规定的接口。

  ●  抽象装饰(Decorator)角色:由FilterInputStream扮演。它实现了InputStream所规定的接口。

  ●  具体装饰(ConcreteDecorator)角色:由几个类扮演,分别是BufferedInputStream、DataInputStream以及两个不常用到的类LineNumberInputStream、PushbackInputStream。

  • 装饰模式和适配模式的区别:适配模式把一个API转化成为另一个API,而装饰模式保持被包装对象的API.

通过java Io里面的类进行讲解:

“inputStreamReader”是字节流向字符流转化的桥梁,但inputStreamReader绝对不是桥梁模式。inputStreamReader是Reader类型,它把一个InputSream的类型包装起来,从而把字节流的API转化成了字符流的API.这是适配器模式的例子。inputStreamReader把InputSream的API适配成了Reader的API.所以inputStreamReader不是装饰模式而是适配模式。同理OutputStreamWriter也是适配模式。

BUfferedReader是一个装饰类,因为它继承Reader,把Reader包装,在Reader的基础上实现了比Reader更强大的功能。但是还是Reader的API.

设计模式(五)学习----装饰模式相关推荐

  1. C#设计模式(学习笔记[01])

    C#设计模式(学习笔记[01])<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office&quo ...

  2. 《游戏设计模式》学习笔记

    ** <游戏设计模式>学习笔记 ** 原作中文版传送门:<游戏设计模式> 原书作者:Bob Nystrom 阅读背景:最近担任了主程(惭愧,整个项目组就我一个人,2333),在 ...

  3. 设计模式总结篇(为什么要学习设计模式,学习设计模式的好处)

    版权声明:转载必须注明本文转自晓_晨的博客:http://blog.csdn.net/niunai112 在学习完设计模式后,LZ想告诉大家: 对于一名工作不久的程序员来说,学习设计模式是非常有必要的 ...

  4. 23种设计模式的学习

    23种设计模式的学习 什么是设计模式 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解. ...

  5. 基于设计模式的学习之旅-----访问者模式(附源码)

    基于设计模式的学习之旅-----访问者模式 1.初始访问者模式 2.什么是访问者模式 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作. 3.模 ...

  6. 「设计模式(五) - 代理模式」

    「设计模式(五) - 代理模式」 一.处处可见的"代理" "代理"在平常生活司空见惯,点外卖,租房子找中介,买飞机票等等.基本上用手机就能完成,也就是不直接接触 ...

  7. 软件设计模式的学习(以Java为例)

    软件设计模式的学习(以Java为例) 单例模型 定义: 懒汉模式 饿汉模式 单例模式的优缺点 优点 缺点 工厂模式 定义 分类 工厂方法模式 抽象工厂模式 代码实现 优点 缺点 文章引用 软件设计模式 ...

  8. 打印鸭子戏水java,《Head first设计模式》学习笔记 #8211; 策略模式,

    <Head first设计模式>学习笔记 – 策略模式, 策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 假设有一个模拟鸭子的游戏,游 ...

  9. 设计模式C++学习笔记之十三(Decorator装饰模式)

    装饰模式,动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator模式相比生成子类更为灵活. 13.1.解释 main(),老爸 ISchoolReport,成绩单接口 CFourthG ...

最新文章

  1. 象过河怎么用远程服务器,象过河远程协助的教程
  2. 中国高校人工智能学院院长 【截止到 2019-05-07】
  3. 服务器被修改,我的世界
  4. Cisco 交換機命名規則
  5. 在内存中读取函数的ShellCode并执行
  6. php类使用自己的静态方法吗,php在类中使用静态方法有几种方式
  7. php网站不能访问,php怎么不登录不能访问
  8. 04. 二维数组中的查找
  9. iosTableView 局部全部刷新以及删除编辑操作
  10. 1 Vue的基础语法
  11. 关于Net Core 多平台程序的Framework问题
  12. 一个校园互联网实验室的纳新试题(我的服务端开发笔试题)
  13. 硬盘整数分区计算方法一般算法
  14. 线性判别分析LDA算法与python实现
  15. 简历是html的怎么改成word文档,word简历使用教程.doc
  16. 朋友圈点赞测试用例~~~脑图
  17. mysql 时区时间_MySql的时区(serverTimezone)引发的血案
  18. hadoop整合hbase
  19. ThinkPHP 微信支付及退款
  20. 探究 LightHouse 工作流程

热门文章

  1. C++的基础知识有哪些?
  2. nginx虚拟域名配置
  3. 无需Docker, 5分钟徒手DIY 一个Linux容器
  4. C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(二)
  5. 解决ubuntu下安装mysql使用service无法启动问题
  6. 分享:开源货币新世界
  7. 垃圾代码评析——关于《C程序设计伴侣》9.4——链表(一)
  8. opencv-python 无法显示图片
  9. phpstrom常用配置
  10. MVC之 自定义过滤器(ActionFilterAttribute)