decorator 装饰

参考:java.io包详细解说

decorator的结构如下:

    MyInterface
       |
_______|_______
|             | 
Myclass     Decorator
          ____|_____
          |        | 
  DecoratorA      DecoratorB


decorator的目的是在不改变任何原有的类的基础下,添加新的功能(你可以理解为书上说的灵活性)。其中Myclass是你要扩展的类,DecoratorA跟DecoratorB封装了你要扩展的功能,并保存有一个MyInterface的引用。

考虑以下代码:myInterface 是myClass的接口,只声明了一个方法print(),myClass实现了该方法:

public interface MyInterface {
public void print();
}

public class MyClass implements MyInterface {
public void print() {
System.out.println("hello");
}
}


那么假如我们要在不改变原来的myClass的基础上,变成输出“hello world!”,要怎么做呢?
当然我们可以考虑直接写个myClass的子类,helloClass之类,但是要是要求根据环境不同,输出"hello world!",my hello world","my Hello"之类的组合呢?
用继承的方式将不得不写一堆类似的子类来。

decorator,装饰模式的解决方法是,只实现基本的功能,把附加的功能抽出来放一边。首先实现一个公用的装饰器接口。

public interface Decorator extends MyInterface {
void print();
}

DecoratorA的功能是打印出my

public class DecoratorA  implements Decorator  {

private MyInterface myObject;

public DecoratorA(MyInterface myObject){
this.myObject=myObject;
}
public void print() {
myObject.print();
System.out.println("my");
}
}

DecoratorB的功能是打印出world

public class DecoratorB  implements Decorator  {

private MyInterface myObject;

public DecoratorB(MyInterface myObject){
this.myObject=myObject;
}

public void print() {
myObject.print();
System.out.println("world");
}
}


这时main函数要打印出 hello my world可简单变为:

new DecoratorB(new DecoratorA(new MyClass())).print();

简单吧?简单的说,就是:
print(){
  print("xxx");//可替换成你要添加的任何处理;
  myObject.print();//调用基础类的函数;
  xxxx;        //后续处理
}

java.io分Stream跟reader、writer两大类,这里只详细介绍Stream,并最后两者间的关系。Stream又分inputStream、OutputStream,两者基本是对称的,这里也只介绍InputStream.

                java.io.InputStream
                        |
 _______________________|________________________
 |                                             |
ByteArrayInputStream                      FilterInputStream
StringBufferInputStream   _____________________|____________________________
FileInputStream           |                |                    |          |
PipedInputStream  DataInputStream BufferedInputStream  LineNumInpuStream XXX

(注:xxx是PushbackInputStream,上面的图放不下)

这个图跟最初介绍的hello world的图很像吧?呵呵。
基础的流只有左边4个,这些流代表了数据的来源,所有的流都必须从这四个中之一开始。(注,还有一个RandomAccessFile、File,这两个不在本文介绍范围)。
然后当我们需要什么添加功能,就从右边中选择一个装饰。例如,我们需要缓存功能,那么需要bufferedInputStream装饰:

BufferdInputStream is = new BufferedInputStream(new FileInputStream("xxx.txt"));

假如再要DataInputStream的功能,只要在加一层:
DataInputStream dis = new DataInputStream(new BufferdInputStream(new FileInputStream));

原文地址:https://www.cnblogs.com/myparamita/p/2203722.html