java_设计模式_装饰者模式_Decorator Pattern(2016-07-28)

 装饰模式又名包装(Wrapper)模式。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。


装饰模式的结构

  装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任。换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。

  装饰模式的类图如下:

  

  在装饰模式中的角色有:

  ●  抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。

  ●  具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类。

  ●  装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。

  ●  具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。

源代码

  抽象构件角色

public interface Component {

    public void sampleOperation();

}

  具体构件角色

public class ConcreteComponent implements Component {

    @Override
    public void sampleOperation() {
        // 写相关的业务代码
    }

}

  装饰角色  

  

public class Decorator implements Component{
    private Component component;

    public Decorator(Component component){
        this.component = component;
    }

    @Override
    public void sampleOperation() {
        // 委派给构件
        component.sampleOperation();
    }

}

  具体装饰角色

public class ConcreteDecoratorA extends Decorator {

    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    @Override
    public void sampleOperation() {
     super.sampleOperation();
        // 写相关的业务代码
    }
}
public class ConcreteDecoratorB extends Decorator {

    public ConcreteDecoratorB(Component component) {
        super(component);
    }

    @Override
    public void sampleOperation() {
      super.sampleOperation();
        // 写相关的业务代码
    }
}

设计模式在JAVA I/O库中的应用

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

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

一.概括介绍Java的I/O

  Java输入/输出功能采用了流的机制,所谓流,就是数据的有序排列,而流可以是从某个源(称为流源或Source of Stream)出来,到某个目的地(称为流汇或Sink of Stream)去的。由流的方向,可以分成输入流和输出流,一个程序从输入流读取数据向输出流写数据。

  如,一个程序可以用FileInputStream类从一个磁盘文件读取数据,如下图所示:

  

像FileInputStream这样的处理器叫做流处理器,它就像流的管道一样,从一个流源吸入某种类型的数据,并输出某种类型的数据。上面这种示意图叫做流的管道图。

 同样道理,也可以用FileOutputStream类向一个磁盘文件写数据,如下图所示:

  

 在实际应用这种机制并不没有太大的用处,程序需要写出地通常是非常结构化的信息,因此这些byte类型的数据实际上是一些数值,文字,源代码等。Java的I/O库提供了一个称做链接(Chaining)的机制,可以将一个流处理器跟另一个流处理器首尾相接,以其中之一的输出为输入,形成一个流管道的链接。

 例如,DataInputStream流处理器可以把FileInputStream流对象的输出当作输入,将Byte类型的数据转换成Java的原始类型和String类型的数据。如下图所示:

 类似地,向一个文件写入Byte类型的数据不是一个简单的过程。一个程序需要向一个文件里写入的数据往往都是结构化的,而Byte类型则是原始类型。因此在写的时候必须经过转换。DataOutputStream流处理器提供了接收了原始数据类型和String数据类型,而这个流处理器的输出数据则是Byte类型。也就是说DataOutputStream可以将源数据转换成Byte类型的数据,再输出来。

 这样一来,就可以将DataOutputStream与FileOutputStream链接起来,这样程序就可以将原始数据类型和String类型的源数据写入这个链接好的双重管道里面,达到将结构化数据写到磁盘文件里面的目的,如下图所示:

 

 流处理器所处理的流必定都有流源,而如果将流类所处理的流源分类的话,基本可以分成两大类:

 第一 数组,String,File等,这一种叫原始流源。

 第二 同样类型的流用做链接流类的流源,叫链接流源。

二.Java I/O库的设计原则

  要理解Java I/O这个庞大而复杂的库,关键是要掌握两个对称性跟两个设计模式模式:

  1.Java I/O库具有两个对称性:

    ①输入-输出对称性,比如InputStream和OutputStream各自占据Byte流的输入与输出的两个平行的等级结构的根部。而Reader和Writer各自占据Char流的输入与输出的两个平行的等级结构的根部。

    ②byte-char对称,InputStream和Reader的子类分别负责Byte和Char流的输入;OutputStream和Writer的子类分别负责Byte和Char流的输出,它们分别形成平行的等级结构。

  2.Java I/O库的两个设计模式:

    ①装饰者模式(Decorator):在由InputStream,OutputStream,Reader和Writer代表的等级结构内部,有一些流处理器可以对另一些流处理器起到装饰作用,形成新的,具有改善了的功能的流处理器。装饰者模式是Java I/O库的整体设计模式。

    ②适配器模式(Adapter):在由InputStream,OutputStream,Reader和Writer代表的等级结构内部,有一些流处理器是对其它类型的流源的适配,这就是适配器模式的应用。

三.装饰模式的应用

  为什么不用继承而用装饰模式

  我们知道Java I/O库需要很多性能的各种组合,如果说这些性能的组合是通过继承方式来实现的话,那么每一种组合都需要一个类,这样就会出现大量重复性问题的出现,从而使类数目“爆炸”。而如果采用装饰模式,那么不仅类的数目大减少了,性能的重复也可以减至到最少。所以装饰模式是Java I/O库的基本模式。

  在这里我想再用<<Head First Design Pattern>>中讲到装饰模式时候的一个例子,看看装饰模式是怎么达到不仅类的数目大减少了,性能的重复也可以减至到最少:

  它这个例子大概是说:Beverage是一个抽象类,它被所有在一个咖啡店里卖的饮料继承。Beverage有个抽象方法cost,所有的子类都要实现这个抽象方法,计算它们的价格。现在有四个最基本的咖啡:HouseBlend,DarkRoast,Decaf,Espresso他们都继承自Beverage,现在的需求是说在四个最基本的咖啡里,每个都可以随便地添加调味品,像steamed milk,soy,还有mocha最后是加上whipped milk。如果是说按继承来实现这种几个调味品跟原来咖啡的组合的话,我们会很自然地设计来下面的类图来:

  

  看到了上面的类图了吗,我们不禁会说这就是“类爆炸”。如果是按装饰模式的设计思路我们可以得出下面的设计类图:

  

 首先是InputStream类型中的装饰模式:

 InputStream有七个直接的具体子类,有四个属于FilterInputStream的具体子类,如下图所示:

  

 

  上图中所有的类都叫做流处理器,这个图就叫做(InputStream类型的)流处理器图。

  根据输入流的源的类型将这些流类分成两种,即原始流类(Original Stream)和链接流处理器(Wrapper Stream)。

  原始流处理器

    原始流处理器接收一个Byte数组对象,String对象,FileDiscriptor对象或者不同类型的流源对象,根据上面的图,原始流处理器包括以下四种:

      ByteArrayInputStream: 为多线程的通信提供缓冲区操作功能,接收一个Byte数组作为流的源。

      FileInputStream:     建立一个与文件有关的输入流。接收一个File对象作为流的源。

      PipedInputStream:    可以与PipedOutputStream配合使用,用于读入一个数据管道的数据,接收一个PipedOutputStream作为源。

      StringBufferInputStream:将一个字符串缓冲区转换为一个输入流。接收一个String对象作为流的源。(JDK帮助文档上说明:已过时。此类未能正确地将字符转换为字节。从JDK1.1开始,从字符串创建流的首选方法是通过StringReader类进行创建。只有字符串中每个字符的低八位可以由此类使用。)

  链接流处理器

    所谓链接流处理器,就是可以接收另一个流对象作为源,并对之进行功能扩展的类。InputStream类型的链接处理器包括以下几种,它们都接收另一个InputStream对象作为流源。

    (1)FilterInputStream称为过滤输入流,它将另一个输入流作为流源。这个类的子类包括以下几种:

        BufferedInputStream:用来从硬盘将数据读入到一个内存缓冲区中,并从缓冲区提供数据。

        DataInputStream:提供基于多字节的读取方法,可以读取原始类型的数据。

        LineNumberInputStream:提供带有行计数功能的过滤输入流。

        PushbackInputStream:提供特殊的功能,可以将已经读取的字节“推回”到输入流中。

    (2)ObjectInputStream可以将使用ObjectInputStream串行化的原始数据类型和对象重新并行化。

    (3)SeqcueneInputStream可以将两个已有的输入流连接起来,形成一个输入流,从而将多个输入流排列构成一个输入流序列。

  抽象结构图

  按照上面的这种原始流处理器和链接流处理器的划分,可以用下面的结构图来描述它们之间的关系。

  

  装饰模式结构图

  

  FilterInputStream继承了InputStream,也引用了InputStream,而它有四个子类,这就是所谓的Decorator模式

  上面这个图向我们传达了这个信息:链接流链接流对象接收一个原始流对象或者另外一个链接流对象作为流源;另一方面他们对流源的内部工作方法做了相应的改变,这种改变是装饰模式所要达到的目的。比如:

    BufferedInputStream“装饰”了InputStream的内部工作方式,使得流的读入操作使用了缓冲机制。在使用了缓冲机制后,不会对每一次的流读入操作都产生一个物理的读盘动作,从而提高了程序的效率,在汲及到物理流的读入时,都应当使用这个装饰流类。

    LineNumberInputStream和PushbackInputStream也同样“装饰”了InputStream的内部工作方式,前者使得程序能够按照行号读入数据;后者能够使程序读入的过程中,退后一个字符。

    DataInputStream子类读入各种不同的原始数据类型以及String类型的数据,这一点可以从它提供的各种read方法看出来,如:readByte(),readInt(),readFloat()等。

其他三种类型中的装饰模式:

  Java语言的I/O库提供了四大等级结构:InputStream,OutputStream,Reader,Writer四个系列的类。InputStream和OutputStream处理8位字节流数据, Reader和Writer处理16位的字符流数据。InputStream和Reader处理输入, OutputStream和Writer处理输出,所以OutputStream,Reader,Writer这三类的装饰模式跟前面详细介绍的InputStream装饰模式大同小异。为了方便比较这几种类型,顺便附上Java语言的I/O层次结构图:

  下面的图表示:以InputStream和OutputStream形成的层次关系  

  

  下面的图表示:以Reader和Writer形成的层次关系

  

四.适配器模式的应用

  不写

内容来源参考:

  http://www.cnblogs.com/java-my-life/archive/2012/04/20/2455726.html

  http://blog.csdn.net/hijiankang/article/details/51027565

  http://blog.csdn.net/ivokky/article/details/9175065

时间: 2024-08-06 05:22:55

java_设计模式_装饰者模式_Decorator Pattern(2016-07-28)的相关文章

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

装饰器模式(Decorator Pattern) 允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能. 通过采用组合.而非继承的手法,Decorator模式实现了在运行时动态地扩展对象功能的能力,而且可以根据需要扩展多个功能.避免了单独使用继承带来的“灵活性差"和"多子类衍生问题". 优点:装饰类和被装饰类可以独立发

09.设计模式_装饰者模式

转载自   http://www.cnblogs.com/zhili/p/DecoratorPattern.html 一.引言 在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).AccessoriesPhone(挂件手机类)等,这样就会导致 "子类爆炸"问题,为了解决这个问题,我们可以使用装饰者模式来动态地给一个对象添加额外的职责.下面让我们看看装饰

java_设计模式_装饰设计模式

package IO; /* * 装饰设计模式 模拟咖啡 * 1.抽象组件:需要装饰的抽象对象(接口或抽象父类) * 2.具体组件:需要装饰的对象 * 3.抽像装饰类:包含了对抽象组件的引用以及装饰着共有的方法 * 4,具体装饰类:被装饰的对象 * */ public class Test2 { public static void main(String[] args) { Drink coffee=new Coffee(); System.out.println(coffee.info()+

设计模式 - 装饰者模式(Decorator Pattern) Java的IO类 使用方法

装饰者模式(Decorator Pattern) Java的IO类 使用方法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26716823 装饰者模式(decorator pattern)参见: http://blog.csdn.net/caroline_wendy/article/details/26707033 Java的IO类使用装饰者模式进行扩展, 其中FilterInputStream类, 就是装饰者(decora

设计模式 - 装饰者模式(Decorator Pattern) 详解

装饰者模式(Decorator Pattern) 详解 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26707033 装饰者模式(Decorator Pattern):动态地将责任附加到对象上. 若要扩展功能, 装饰者提供了比继承更有弹性的替代方案. 使用方法: 1. 首先创建组件(Component)父类, 所有类,具体组件(Concrete Component)和装饰者(Decorator)都属于这一类型, 可以进行扩展

Design Pattern 设计模式 Decorator 装饰者模式

1 设计一个基类 2 继承这个基类,并包含这个基类的一个对象 3 创建继承类的时候,初始化这个基类,因为是基类指针,所以可以是所有基类的衍生类对象,那么就可以叠加任意多个衍生类对象了. 关键是在衍生类中包含一个基类对象,然后有了继承和包含两重关系,可以使得一个类一个类对象叠加,达到装饰目的. 等于是创建了一个对象指针链表,一个一个对象发挥其相应的作用. 下面程序装饰一个桌子,同时包含释放内存的处理. 关键要知道基类的析构函数必须使用虚函数,为什么? 1 如果基类不是析构函数,那么如果衍生类中包含

设计模式 - 装饰者模式(Decorator Pattern) 具体解释

装饰者模式(Decorator Pattern) 具体解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26707033 装饰者模式(Decorator Pattern):动态地将责任附加到对象上. 若要扩展功能, 装饰者提供了比继承更有弹性的替代方案. 用法: 1. 首先创建组件(Component)父类, 全部类,详细组件(Concrete Component)和装饰者(Decorator)都属于这一类型, 能够进行扩展

设计模式 - 装饰者模式(Decorator Pattern) Java的IO类 用法

装饰者模式(Decorator Pattern) Java的IO类 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26716823 装饰者模式(decorator pattern)參见: http://blog.csdn.net/caroline_wendy/article/details/26707033 Java的IO类使用装饰者模式进行扩展, 当中FilterInputStream类, 就是装饰者(decorato

java设计模式之 装饰器模式

适AT java设计模式之 装饰器模式 装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构. 这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,动态给一个对象添提供了额外的功能. 我们通过下面的实例来演示装饰器模式的用法.模拟一个人从想吃饭.找饭店.享受美食.结束吃饭的过程 代码展示: 首先创建一个被修饰的接口 Eat package deco