2.1 适配器和装饰器的区别
1. 适配器
- 适配器是把一个API包装成另一个API;
- 适配者和被适配者实现的接口不同;
2. 装饰器
- 装饰器是保留被包装的原API;
- 装饰者和被装饰者实现相同的接口(只是增加更多)
2.2 适配器和装饰器的相同点
1. 都是结构模式
2. 都是wrapper模式
2.3 wrapper模式(适配器/装饰器)与代理模式的对比
1. wrapper模式
- wrapper是把一个API转成另一个API(适配), 或者用另一个API来增强原有的API(装饰);
2. 代理模式
- 代理是用一个API来替代+增强原有的API;
代理分两种: 通过接口代理和通过类
3. 代理模式-接口型(java中动态代理)
代理类需要实现和被代理的类相同的接口, 然后在代理类实现中使用和增强被代理的原API;
4. 代理模式-类(CGLib代理)
代理类要代理的目标没有接口, 这样的话, 代理类需要继承被代理类, 来做代理和增强API的逻辑;
2.4 适配器-案例-(java.io包)
2.4.1 InputStream和OutputStream适配:
ByteArrayInputStream
FileInputStream
BufferedInputStream
PipedInputStream
StringBufferInputStream(无对应的Output)
ByteArrayOutputStream
FileOutputStream
BufferedOutputStream
PipedOutputStream
- ByteArrayInputStream
public ByteArrayInputStream extends InputStream {
protected byte buf[];
.....
}
用一个
byte buf[]
byte数组来适配成 InputStream 流处理器的接口;
- FileInputStream
public FileInputStream extends InputStream{
/* File Descriptor - handle to the open file */
private final FileDescriptor fd;
...
}
用一个 FileDescriptor 来适配成一个 InputStream 流处理器的接口;
- StringBufferInputStream
@Deprecated
public class StringBufferInputStream extends InputStream{
/**
* The string from which bytes are read.
*/
protected String buffer;
...
}
用一个 String 来适配成一个 InputStream 流处理器的接口;
- BufferedInputStream
public class BufferedInputStream extends FilterInputStream {
private static int DEFAULT_BUFFER_SIZE = 8192;
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
/**
* The internal buffer array where the data is stored. When necessary,
* it may be replaced by another array of a different size.
*/
protected volatile byte buf[];
跟 ByteArrayInputStream 类似, 用一个
byte buf[]
byte数组来适配成 InputStream 流处理器的接口;
- PipedInputStream
public class PipedInputStream extends InputStream {
boolean closedByWriter = false;
volatile boolean closedByReader = false;
boolean connected = false;
/* REMIND: identification of the read and write sides needs to be more sophisticated.
Either using thread groups (but what about pipes within a thread?)
or using finalization (but it may be a long time until the next GC).
*/
Thread readSide;
Thread writeSide;
private static final int DEFAULT_PIPE_SIZE = 1024;
/**
* The default size of the pipe's circular input buffer.
* @since JDK1.1
*/
// This used to be a constant before the pipe size was allowed
// to change. This field will continue to be maintained
// for backward compatibility.
protected static final int PIPE_SIZE = DEFAULT_PIPE_SIZE;
/**
* The circular buffer into which incoming data is placed.
* @since JDK1.1
*/
protected byte buffer[];
使用一读一写两个线程和一个 byte数组, 来适配成 InputStream 流处理器的接口;
Output部分略去代码说明
2.4.2. Reader和Writer适配
BufferedReader
CharArrayReader
StringReader
PipedReader
BufferedWriter
CharArrayWriter
StringWriter
PipedWriter
略去代码
2.4.3. byte流到char流的适配
- InputStreamReader
- OutputStreamWriter
public class InputStreamReader extends Reader {
private final StreamDecoder sd;
...
}
用sun.nio.cs.StreamDecoder 适配 InputStream为Reader, 字节到字符
public class OutputStreamWriter extends Writer {
private final StreamEncoder se;
...
}
用sun.nio.cs.StreamEncoder适配 InputStream为Reader, 字节到字符
2.5 装饰器-案例(java.io包)
2.5.1 装饰器-BufferedReader
BufferedReader br = new BufferedReader(new FileReader("f.txt"));
- br除了有文件读取和转换功能,还提供了缓存读取(buffered)功能;
- br增加了readLine()方法,可以逐行的读取文件。这里增加了Reader类没有的功能, 有些破坏装饰器模式的意味 感觉好像有转为适配器模式的影子;
所以, 只能称呼 BufferedReader: 是一个装饰类, 但不是一个100%的装饰类, 因为他增加了 readLine()新方法;
一个装饰类实现的新方法越多, 偏离纯装饰类的就越远!
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 hi@niewj.com