转自http://blog.csdn.net/hust_is_lcd/article/details/7884320

1.认识装饰器模式

装饰模式能够实现动态的为对象添加功能,是从一个对象外部来给对象添加功能。通常给对象添加功能,要么直接修改对象添加相应的功能,要么派生对应的子类来扩展,抑或是使用对象组合的方式。显然,直接修改对应的类这种方式并不可取。在面向对象的设计中,而我们也应该尽量使用对象组合,而不是对象继承来扩展和复用功能。装饰器模式就是基于对象组合的方式,可以很灵活的给对象添加所需要的功能。装饰器模式的本质就是动态组合。动态是手段,组合才是目的。总之,装饰模式是通过把复杂的功能简单化,分散化,然后再运行期间,根据需要来动态组合的这样一个模式。

2.模式结构和说明

装饰模式的结构如下图所示。

Component:组件对象的接口,可以给这些对象动态的添加职责;

ConcreteComponent:具体的组件对象,实现了组件接口。该对象通常就是被装饰器装饰的原始对象,可以给这个对象添加职责;

Decorator:所有装饰器的父类,需要定义一个与组件接口一致的接口(主要是为了实现装饰器功能的复用,即具体的装饰器A可以装饰另外一个具体的装饰器B,因为装饰器类也是一个Component),并持有一个Component对象,该对象其实就是被装饰的对象。如果不继承组件接口类,则只能为某个组件添加单一的功能,即装饰器对象不能在装饰其他的装饰器对象。

ConcreteDecorator:具体的装饰器类,实现具体要向被装饰对象添加的功能。用来装饰具体的组件对象或者另外一个具体的装饰器对象。

装饰器模式的示例代码如下(Java语言描述):

(1)组件对象的接口,可以给这些对象动态的添加职责

public abstract class Component {
/**
* 示例方法
*/
public abstract void operation();
}

(2)具体实现组件对象接口的对象

public class ConcreteComponent extends Component {

	public void operation() {
//相应的功能处理
} }

(3)装饰器接口,维持一个指向组件对象的接口对象, 并定义一个与组件接口一致的接口

public abstract class Decorator extends Component {
/**
* 持有组件对象
*/
protected Component component; /**
* 构造方法,传入组件对象
* @param component 组件对象
*/
public Decorator(Component component) {
this.component = component;
} public void operation() {
//转发请求给组件对象,可以在转发前后执行一些附加动作
component.operation();
} }

(4)装饰器的具体实现对象,向组件对象添加职责,operationFirst(),operationLast()为前后需要添加的功能。具体的装饰器类ConcreteDecoratorB代码相似,不在给出。

public class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
private void operationFirst(){ } //在调用父类的operation方法之前需要执行的操作
private void operationLast(){ } //在调用父类的operation方法之后需要执行的操作
public void operation() {
//调用父类的方法,可以在调用前后执行一些附加动作
operationFirst(); //添加的功能
super.operation(); //这里可以选择性的调用父类的方法,如果不调用则相当于完全改写了方法,实现了新的功能
operationLast(); //添加的功能
}
}

(5) 客户端使用装饰器的代码

public class Client{
public static void main(String[] args){
Component c1 = new ConcreteComponent (); //首先创建需要被装饰的原始对象(即要被装饰的对象)
Decorator decoratorA = new ConcreteDecoratorA(c1); //给对象透明的增加功能A并调用
decoratorA .operation();
Decorator decoratorB = new ConcreteDecoratorB(c1); //给对象透明的增加功能B并调用
decoratorB .operation();
Decorator decoratorBandA = new ConcreteDecoratorB(decoratorA);//装饰器也可以装饰具体的装饰对象,此时相当于给对象在增加A的功能基础上在添加功能B
decoratorBandA.operation();
}
}

3.小结

Java中的IO是明显的装饰器模式的运用。FilterInputStream,FilterOutputStream,FilterRead,FilterWriter分别为具体装饰器的父类,相当于Decorator类,它们分别实现了InputStream,OutputStream,Reader,Writer类(这些类相当于Component,是其他组件类的父类,也是Decorator类的父类)。继承自InputStream,OutputStream,Reader,Writer这四个类的其他类是具体的组件类,每个都有相应的功能,相当于ConcreteComponent类。而继承自FilterInputStream,FilterOutputStream,FilterRead,FilterWriter这四个类的其他类就是具体的装饰器对象类,即ConcreteDecorator类。通过这些装饰器类,可以给我们提供更加具体的有用的功能。如FileInputStream是InputStream的一个子类,从文件中读取数据流,BufferedInputStream是继承自FilterInputStream的具体的装饰器类,该类提供一个内存的缓冲区类保存输入流中的数据。我们使用如下的代码来使用BufferedInputStream装饰FileInputStream,就可以提供一个内存缓冲区来保存从文件中读取的输入流。

    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); //其中file为某个具体文件的File或者FileDescription对象

在以下两种情况下可以考虑使用装饰器模式:

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

(2)如果不适合使用子类来进行扩展的时候,可以考虑使用装饰器模式。

装饰器模式(Decorator)的更多相关文章

  1. 【PHP设计模式 09_ZhuangShiQi.php】装饰器模式 (decorator)

    <?php /** * [装饰器模式 (decorator)] * 有时候发布一篇文章需要经过很多人手,层层处理 */ header("Content-type: text/html; ...

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

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

  3. 装饰器模式-Decorator(Java实现)

    装饰器模式-Decorator(Java实现) 装饰器模式允许向一个现有的对象添加新的功能, 同时又不改变其结构. 其中 "现有对象"在本文中是StringDisplay类. 添加 ...

  4. 说说设计模式~装饰器模式(Decorator)~多功能消息组件的实现

    返回目录 为何要设计多功能消息组件 之前写过一篇装饰器模式的文章,感觉不够深入,这次的例子是实现项目中遇到的,所以把它拿出来,再写写,之前也写过消息组件的文章,主要采用了策略模式实现的,即每个项目可以 ...

  5. 设计模式入门之装饰器模式Decorator

    //装饰模式定义:动态地给一个对象加入一些额外的职责. //就添加功能来说.装饰模式比生成子类更为灵活 //这也提现了面向对象设计中的一条基本原则,即:尽量使用对象组合,而不是对象继承 //Compo ...

  6. 装饰器模式(Decorator)——深入理解与实战应用

    本文为原创博文,转载请注明出处,侵权必究! 1.初识装饰器模式 装饰器模式,顾名思义,就是对已经存在的某些类进行装饰,以此来扩展一些功能.其结构图如下: Component为统一接口,也是装饰类和被装 ...

  7. 装饰器模式 Decorator 结构型 设计模式 (十)

    引子           现实世界的装饰器模式 大家应该都吃过手抓饼,本文装饰器模式以手抓饼为模型展开简介 "老板,来一个手抓饼,  加个培根,  加个鸡蛋,多少钱?" 这句话会不 ...

  8. 设计模式学习心得<装饰器模式 Decorator>

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

  9. 23种设计模式之装饰器模式(Decorator Pattern)

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

随机推荐

  1. Linux远程备份—ftp方式、NFS方式

    问题:现在项目中每天都有从其它各个系统发过来的数据文件(存放在/var/data目录下,以.txt结尾),虽然很久以前的文件很少用到,占用了很多空间,却不能删除.于是,想把一个月以前的文件都压缩了传到 ...

  2. 【git】借助github学习成果

    1.创建分支 git branch dev   //创建分支 git checkout dev  //切换分支 或者用一句  git checkout -b dev 删除一个分支  git check ...

  3. easy ui 表单提交添加遮罩,避免数据重复提交

    如下图: //点击提交按钮保存数据 $('#btn_submit').click(function () { //增加遮罩层 $.messager.progress({ title: '温馨提示', ...

  4. Lua基础之table详解

    概要:1.table特性:2.table的构造:3.table常用函数:4.table遍历:5.table面向对象 原文地址:http://blog.csdn.net/dingkun520wy/art ...

  5. 3.4 spring- lookup-method 子元素的使用与解析

    1. lookup-method的应用: 1.1 子元素lookup-method 似乎不是很常用,但是在某些时候他的确是非常有用的属性,通常我们称它为 "获取器注入" . 引用 ...

  6. webApp添加到iOS桌面

    iOS中的safri浏览器可以将一个网页添加到桌面,当做一个独立的应用运行. 当然,这里我们不讨论怎么去做一个webApp,这需要html5的相关知识和开发经验.这里我们只讲webApp添加桌面后到启 ...

  7. 安装ADT Cannot complete the install because one or more required items could not be found.

    点击进行安装,将会弹出 错误提示是: Cannot complete the install because one or more required items could not be found ...

  8. 阿里云PHP Redis代码示例

    测试代码示例 <?php /* 这里替换为连接的实例host和port */ $host = "localhost"; $port = 6379; /* 这里替换为实例id和 ...

  9. Windows10搭建PHP7开发环境

    原文:Windows10搭建PHP7开发环境 3年前写了一篇<Windows下搭建PHP开发环境>之后就再也没有碰过PHP了,最近新发布了PHP7然后回去看了一下之前写的文章,发现很多配置 ...

  10. 搜索插件:ack.vim

    ack.vim是Perl脚本ack的前端,对于Vim,也是grepprg和quickfix的简单封装,非常适合搜索 github地址为 https://github.com/mileszs/ack.v ...