Java IO : 流,以及適配器模式的應用html
適配器實際上是分爲對象適配器和類適配器兩種,兩種的工做原理不太同樣。java
對象適配器是使用組合的方法,在Adapter中會保留一個原對象(Adaptee)的引用,適配器的實現就是講Target中的方法委派給Adaptee對象來作,用Adaptee中的方法實現Target中的方法。數組
這種類型的好處就是,Adpater只須要實現Target中的方法就行了。ide
與對象適配器不一樣的是,類適配器是經過類的繼承來實現的。Adpater直接繼承了Target和Adaptee中的全部方法,並進行改寫,從而實現了Target中的方法。this
以上摘自 http://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/adapter.html編碼
以ByteArrayInputStream爲例,ByteArrayInputStream是一個基於對象的適配器,以下所示,.net
public class ByteArrayInputStream extends InputStream { /** * An array of bytes that was provided * by the creator of the stream. */ protected byte buf[]; /** * The index of the next character to read from the input stream buffer. */ protected int pos; protected int mark = 0; protected int count; public ByteArrayInputStream(byte buf[]) { this.buf = buf; this.pos = 0; this.count = buf.length; } public ByteArrayInputStream(byte buf[], int offset, int length) { this.buf = buf; this.pos = offset; this.count = Math.min(offset + length, buf.length); this.mark = offset; } public synchronized int read() { return (pos < count) ? (buf[pos++] & 0xff) : -1; } public synchronized int read(byte b[], int off, int len) { if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } if (pos >= count) { return -1; } int avail = count - pos; if (len > avail) { len = avail; } if (len <= 0) { return 0; } System.arraycopy(buf, pos, b, off, len); pos += len; return len; } public synchronized long skip(long n) { long k = count - pos; if (n < k) { k = n < 0 ? 0 : n; } pos += k; return k; } public synchronized int available() { return count - pos; } public boolean markSupported() { return true; } public void mark(int readAheadLimit) { mark = pos; } public synchronized void reset() { pos = mark; } public void close() throws IOException { } }
ByteArrayInputStream 內部維護了一個 byte buf[] 數組,經過繼承 InputStream 的方法適配了對 buf[] 的讀取。翻譯
StringBufferInputStream繼承了InputStream類型,同時持有一個對 String 對象的引用,將 String 對象適配成InputStream類型的對象的適配器模式。code
從byte流到char流的適配htm
在java語言的標準庫 java I/O 裏面,有一個InputStreamReader類叫作橋樑(bridge)類。InputStreamReader是從byte流到char流的一個橋樑,它讀入byte數據並根據指定的編碼將之翻譯成char數據。 InputStreamReader雖然叫「橋樑」,但它不爽橋樑模式,是適配器模式的應用。 InputStreamReader InputStreamReader是從byte輸入流到char輸入流的一個適配器。下圖所示就是InputStreamReader 的結構
/** * An InputStreamReader is a bridge from byte streams to character streams: It * reads bytes and decodes them into characters using a specified {@link * java.nio.charset.Charset <code>charset</code>}. */ public class InputStreamReader extends Reader { private final StreamDecoder sd; public InputStreamReader(InputStream in) { super(in); try { sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object } catch (UnsupportedEncodingException e) { // The default encoding should always be available throw new Error(e); } } public InputStreamReader(InputStream in, String charsetName) throws UnsupportedEncodingException { super(in); if (charsetName == null) throw new NullPointerException("charsetName"); sd = StreamDecoder.forInputStreamReader(in, this, charsetName); } public InputStreamReader(InputStream in, Charset cs) { super(in); if (cs == null) throw new NullPointerException("charset"); sd = StreamDecoder.forInputStreamReader(in, this, cs); } public InputStreamReader(InputStream in, CharsetDecoder dec) { super(in); if (dec == null) throw new NullPointerException("charset decoder"); sd = StreamDecoder.forInputStreamReader(in, this, dec); } public String getEncoding() { return sd.getEncoding(); } public int read() throws IOException { return sd.read(); } public int read(char cbuf[], int offset, int length) throws IOException { return sd.read(cbuf, offset, length); } public boolean ready() throws IOException { return sd.ready(); } public void close() throws IOException { sd.close(); } }
爲了說明適配器類InputStreamReader是如何使用,請看下面例子。Echo類能夠將控制檯輸入的任何字符串重新打印出來,源代碼以下:
public class Echo { public static void main(String[] args) throws IOException { String line; InputStreamReader input = new InputStreamReader(System.in); System.out.println("Enter data and push enter:"); BufferedReader reader = new BufferedReader(input); line = reader.readLine(); System.out.println("Data entered :" + line); } }
能夠看出,這個類接受一個類型爲inputStream的System.in對象,將之適配成Reader類型,而後再使用
BufferedReader類「裝飾」它,將緩衝功能加上去。這樣一來,就能夠使用BufferedReader對象的readerLine() 方法讀入整行的輸入數據,數據類型是String。
參考:https://my.oschina.net/gao0516/blog/136103
============END============