职责

  装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

  装饰模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能,使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。

  1,不改变原类文件。

  2,不使用继承。

  3,动态扩展。

实现细节

Component抽象构件角色:

  真实对象和装饰对象有相同的接口。这样,客户端对象就能够以与真实对象相同的方式同装饰对象交互。

ConcreteComponent 具体构件角色(真实对象):

   io流中的FileInputStream、FileOutputStream

Decorator装饰角色:

   持有一个抽象构件的引用。装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象。这样,就能在真实对象调用前后增加新的功能。

ConcreteDecorator具体装饰角色:

  负责给构件对象增加新的责任。

装饰(Decorator)模式代码示例

代码

package com.cnki.decorator;

/**
* 抽象构建
* @author Administrator
*
*/
public interface ICar {
void move();
} //ConcreteComponent 具体构件角色(真实对象)
class Car implements ICar {
@Override
public void move() {
System.out.println("陆地上跑!");
}
} //Decorator装饰角色
class SuperCar implements ICar {
protected ICar car;
public SuperCar(ICar car) {
super();
this.car = car;
} @Override
public void move() {
car.move();
}
} //ConcreteDecorator具体装饰角色
class FlyCar extends SuperCar { public FlyCar(ICar car) {
super(car);
} public void fly(){
System.out.println("天上飞!");
} @Override
public void move() {
super.move();
fly();
} } //ConcreteDecorator具体装饰角色
class WaterCar extends SuperCar { public WaterCar(ICar car) {
super(car);
} public void swim(){
System.out.println("水上游!");
} @Override
public void move() {
super.move();
swim();
} } //ConcreteDecorator具体装饰角色
class AICar extends SuperCar { public AICar(ICar car) {
super(car);
} public void autoMove(){
System.out.println("自动跑!");
} @Override
public void move() {
super.move();
autoMove();
} }

测试

package com.cnki.decorator;

import java.io.FileInputStream;
import java.io.InputStreamReader; public class Client {
public static void main(String[] args) {
Car car = new Car();
car.move(); System.out.println("增加新的功能,飞行----------");
FlyCar flycar = new FlyCar(car);
flycar.move(); System.out.println("增加新的功能,水里游---------");
WaterCar waterCar = new WaterCar(car);
waterCar.move(); System.out.println("增加两个新的功能,飞行,水里游-------");
WaterCar waterCar2 = new WaterCar(new FlyCar(car));
waterCar2.move(); // Reader r = new BufferedReader(new InputStreamReader(new FileInputStream(new File("d:/a.txt")))); }
}

开发中使用的场景

  IO中输入流和输出流的设计

  Swing包中图形界面构件功能

  Servlet API 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,HttpServletRequestWrapper 类,增强了request对象的功能。

  Struts2中,request,response,session对象的处理

IO流实现细节

  Component抽象构件角色:

  io流中的InputStream、OutputStream、Reader、Writer

  ConcreteComponent 具体构件角色:

  io流中的FileInputStream、FileOutputStream

  Decorator装饰角色:

  持有一个抽象构件的引用:io流中的FilterInputStream、FilterOutputStream

  ConcreteDecorator具体装饰角色:

  负责给构件对象增加新的责任。Io流中的BufferedOutputStream、BufferedInputStream等。

小结  

优点

  装饰模式(Decorator)也叫包装器模式(Wrapper)

  装饰模式降低系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。

  扩展对象功能,比继承灵活,不会导致类个数急剧增加

  可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象

  具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构件子类和具体装饰子类。

  总之呢,装饰器模式就是一个可以非常灵活的动态扩展类功能的设计模式,它采用组合的方式取代继承,使得各个功能的扩展更加独立和灵活。

缺点

  产生很多小对象。大量小对象占据内存,一定程度上影响性能。

  装饰模式易于出错,调试排查比较麻烦。

装饰模式和桥接模式的区别

  两个模式都是为了解决过多子类对象问题。但他们诱因不一样。

  桥模式是对象自身现有机制沿着多个维度变化,是既有部分不稳定。

  装饰模式是为了增加新的功能。

④ 设计模式的艺术-10.装饰(Decorator)模式的更多相关文章

  1. 设计模式C++描述----10.装饰(Decorator)模式

    一. 举例 我之前做过一个文件系统就叫 MyFileSys 吧,后来的话,客户想加入一些附加功能,比如压缩.加密.杀毒之类的操作,这些附加操作没有先后顺序,比如你可以先压缩再加密,也可以先杀毒再压缩, ...

  2. 《Head First 设计模式》ch.3 装饰(Decorator)模式

    设计原则 类应该对修改关闭,对扩展开放(开放-关闭原则).在每个地方使用开放-关闭原则是一种浪费,也没有必要,因为这通常会引入新的抽象层次,增加代码复杂度.需要把注意力集中在设计中最有可能改变的地方. ...

  3. 设计模式(八)装饰器模式Decorator(结构型)

    设计模式(八)装饰器模式Decorator(结构型) 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法 ...

  4. php设计模式课程---7、装饰器模式如何使用

    php设计模式课程---7.装饰器模式如何使用 一.总结 一句话总结: 装饰器的核心是获取了文章类整个类,而不是获取了文章内容,有了这个文章类,我想给你加多少装饰就给你加多少装饰(将文章这个类封装进去 ...

  5. 大型Java进阶专题(八)设计模式之适配器模式、装饰者模式和观察者模式

    前言 ​ 今天开始我们专题的第八课了.本章节将介绍:三个设计模式,适配器模式.装饰者模式和观察者模式.通过学习适配器模式,可以优雅的解决代码功能的兼容问题.另外有重构需求的人群一定需要掌握装饰者模式. ...

  6. 设计模式(九)——装饰者模式(io源码分析)

    1 星巴克咖啡订单项目(咖啡馆): 1) 咖啡种类/单品咖啡:Espresso(意大利浓咖啡).ShortBlack.LongBlack(美式咖啡).Decaf(无因咖啡) 2) 调料:Milk.So ...

  7. 装饰(Decorator)模式

    1.装饰(Decorator)模式    动态给一个对象添加一些额外的职责.就增加功能来说,装饰模式比生成子类更为灵活.Component是定义一个对象接口.可以给这些对象动态地添加职责.Concre ...

  8. 设计模式之第10章-桥接模式(Java实现)

    设计模式之第10章-桥接模式(Java实现) “一入软件深似海,从此早睡是路人.黑夜给了我黑色的眼睛,我却用他去寻找八阿哥.”“怎么了,又来那么多的感慨啊.”“还能有什么啊,老板是说让换个APP做,这 ...

  9. 设计模式的征途—10.装饰(Decorator)模式

    虽然目前房价依旧很高,就连我所在的成都郊区(非中心城区)的房价均价都早已破万,但却还是阻挡不了大家对新房的渴望和买房的热情.如果大家买的是清水房,那么无疑还有一项艰巨的任务在等着大家,那就是装修.对新 ...

随机推荐

  1. Alpha冲刺——第十天

    Alpha第十天 听说 031502543 周龙荣(队长) 031502615 李家鹏 031502632 伍晨薇 031502637 张柽 031502639 郑秦 1.前言 任务分配是VV.ZQ. ...

  2. C语言的知识与能力的自评

    1.我希望将来上班的地方是自己所感兴趣的,正在寻找自己感兴趣的,并且正在普及IT行业的相关知识. 2.我认为学习就是一个自我成长和自我提升以及认识世界的方法,学习的作用是可以不断的提升对这个世界的认识 ...

  3. Java 成员初始化顺序

    package com.cwcec.test; class Fu { int num = 5; //构造代码块 { System.out.println("Fu constructor co ...

  4. jdbc 4.0

    1.存储MySQL数据库的date.time.timestamp.datetime以及year类型数据 package com.rong.jielong; import java.sql.Connec ...

  5. 成功解决JSP和Servlet的中文乱码问题

    表单提交时出现乱码: 在进行表单提交的时候,经常提交一些中文,自然就避免不了出现中文乱码的情况,对于表单来说有两种提交方式:get和post提交方式.所以请求的时候便有get请求和post请求.以前我 ...

  6. socket与TCP/UDP编程~

    ket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序.要学Internet上的TCP/IP网络编程,必须理解Socket接口. ...

  7. 第210天:node、nvm、npm和gulp的安装和使用详解

    一.node 1.什么是node? 它不是JS文件,也不是JS框架,而是Server side JavaScript runtime,当服务端的一个JS文件运行时,会被NODE拦截,在NODE中运行J ...

  8. 【bzoj2257】[Jsoi2009]瓶子和燃料 扩展裴蜀定理+STL-map

    题目描述 给出 $n$ 个瓶子和无限的水,每个瓶子有一定的容量.每次你可以将一个瓶子装满水,或将A瓶子内的水倒入B瓶子中直到A倒空或B倒满.从中选出 $k$ 个瓶子,使得能够通过这 $k$ 个瓶子凑出 ...

  9. BZOJ1996 HNOI2010合唱队(区间dp)

    设f[i][j][0/1]表示i~j这段区间上一次选择的是最左/最右人的方案数.转移显然. #include<iostream> #include<cstdio> #inclu ...

  10. 【NOI2006】聪明的导游

    [NOI2006]聪明的导游 题面 洛谷 题目描述 小佳最近迷上了导游这个工作,一天到晚想着带游客参观各处的景点.正好 M 市在举行 NOI,来参观的人特别的多.不少朋友给小佳介绍了需要导游的人. M ...