java 装饰器模式

来源:互联网 发布:mac截图保存位置 编辑:程序博客网 时间:2024/04/29 05:41

http://eneasy.iteye.com/blog/174840

http://www.cnblogs.com/ikuman/archive/2013/01/29/2877913.html


1.意图: 

    在一个对象的外围创建一个称为装饰器的封装,动态地给这个对象添加一些额外的功能。 

2.类图: 
     

3.原理: 
      在一个对象的外围创建一个称为装饰器的封装,动态地给这个对象添加一些额外的功能。以对客户端透明的方式扩展对象的功能。 
       装饰器模式又称为包裹模式(wrapper),因为一个具体装饰器都将下一个具体装饰器或具体构件类包裹起来。如有三个装饰器类Decorator1, Decorator2, Decorator3,它们的典型的创建过程为new Decorator1(new Decorator2(new Decorator3(new ConcreteComponent()))). 

    这样Decorator1包裹了Decorator2,Decorator2包裹了Decorator3,Decorator3包裹了ConcreteComponent对象,每一层包裹都提供了新的功能。如图: 




interface Person {void doCoding();}class Employee implements Person {public void doCoding() {System.out.println("程序员写程序");}}abstract class Manager implements Person {public abstract void doCoding();}class ManagerA extends Manager {private Person person;public ManagerA(Person person) {super();this.person = person;}public void doCoding() {doEarlyWork();person.doCoding();}public void doEarlyWork() {System.out.println("项目经理A做需求分析");System.out.println("项目经理A做架构设计");}}class ManagerB extends Manager {private Person person;public ManagerB(Person person) {super();this.person = person;}public void doCoding() {person.doCoding();doEndWork();}public void doEndWork() {System.out.println("项目经理B做收尾工作");}}public class Decorator {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubPerson employee = new Employee();employee = new ManagerA(employee);employee = new ManagerB(employee);employee.doCoding();  }}

项目经理A做需求分析
项目经理A做架构设计
程序员写程序
项目经理B做收尾工作


优点: 

    装饰器与继承的目的都是扩展对象的功能,但装饰器提供了比继承更大的灵活性,可以动态的决定是“粘上”还是“去掉”一个装饰。 
      通过使用不同的具体装饰类和这些类的排列组合,可以创建出很多不同行为的组合。 

    缺点: 

    装饰器比继承关系使用更少的类,但比继承关系使用更多的对象,更多的对象会使查错变得更困难,特别是这些对象看上去很像的时候。 

实际应用中的例子:java i/o




还是head first中的图清晰明了



第二层是concretcomponents和abstract decorator

concretcomponents是实现具体或者核心任务的类(负责实际将磁盘上的数据读入到内存), concret decorators只是在这个核心任务类的基础上做些前处理或者后处理的事情

第三层是concret decorators,实现的是对某一个concret component和其他concrete decorator的包装或者修饰

比如,InputStream in = new  BufferedInputStream(new FileInputStream("txt"));

FileInputStream是一个concrete component, 其作用是读取磁盘上的文件,将其的一个对象给BufferedInputStream对象的一个成员变量,其中BufferedInputStream是一个concrete decorator, 由具体的修饰类对具体成分类进行“后处理”或者“预处理”,其作用就是调用FileInputStream读取磁盘上的文件,但是在BufferedInputStream内部使用缓冲区,加速文件读取。

也可以写成这样的形式

InputStream in = new LineNumberInputStream(new BufferedInputStream(new FileInputStream("tt")));

具体修饰类可以多次“包装”


可以自己实现一个具体修饰类

import java.io.BufferedInputStream;import java.io.FileInputStream;import java.io.FilterInputStream;import java.io.IOException;import java.io.InputStream;//concrete decoratorclass LowerInputStream extends FilterInputStream {public LowerInputStream(InputStream in) {super(in);}public int read() throws IOException {int c = super.read();return (c == -1? c: Character.toLowerCase((char)c));}public int read(byte[]b, int offset, int len) throws IOException {int result = super.read(b, offset, len);for (int i = 0; i < len; ++i) {b[i] = (byte)Character.toLowerCase((char)b[i]);}return result;}}public class Decorator {public static void main(String[] args) throws Exception{// TODO Auto-generated method stubInputStream in = new LowerInputStream(new BufferedInputStream(new FileInputStream("tt")));int c;while((c = in.read()) >=0) {System.out.print((char)c);}}}


上面分析的是面向字节流的类,接下来分析面向字符流的

其中最重要的是InputStreamReader,起到将字节流按照指定编码改变为字符流的作用


从上图可以看到,StreamDecoder是一个适配器,将InputStream字节流,按照Reader的接口改变成字符流

其实InputStreamReader也可以看做一个适配器,将StreamDecoder,按照Reader接口进行改装




如果把InputStreamReader看做一个具体component,那么BufferedReader就是一个具体的修饰类

所以,我们通常这样写

BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("D:/cplus/norm/norm/exp"), "UTF-8"));