Java IO流以及裝飾器模式在其上的運用
流概述
Java中,流是一種有序的位元組序列,可以有任意的長度。從應用流向目的地稱為輸出流,從目的地流向應用稱為輸入流。
Java的流族譜
Java的 java.io 包中囊括了整個流的家族,輸出流和輸入流的譜系如下所示:
InputStream和OutputStream
InputStream和OutputStream分別是輸入輸出流的頂級抽象父類,只定義了一些抽象方法供子類實現。
在輸出流OutputStream中,如果你需要向一個輸出流寫入資料,可以呼叫 void write(int b) 方法,這個方法會將b的低八位寫入流中,高24位將會被自動忽略。如果想要批量寫入資料呢,那麼可以呼叫 void write(byte[] b) 方法將一個位元組陣列的內容全部寫入流中,同時還有 void write(byte[] b, int off, int len) 可以讓你指定從哪裡寫入多少資料。
如果你希望你向流中寫入的資料能夠儘快地輸送到目的地,比如說檔案,那麼可以在寫入資料後,呼叫 flush() 方法將當前輸出流刷到作業系統層面的緩衝區中。不過需要注意的是,此方法並不保證資料立馬就能刷到實際的物理目的地(比如說儲存)。
使用完流後應該呼叫其 close() 方法將流關閉,流關閉時,將會先flush,後關閉。
在輸入流InputStream中,可以通過 int read() 方法來從流中讀取一個位元組,批量讀取位元組可以通過 int read(byte[] b) 或者 int read(byte[] b, int off, int len) 來實現,這兩個方法的返回值為實際讀取到的位元組數。如果需要重複讀取流中某段資料,可以在讀取之前先使用 void mark(int readlimit) 方法在當前位置做一個記號,之後通過 void reset() 方法返回到之前做標記的位置,不過在做這些標記操作之前,需要先通過 boolean markSupported() 方法來確定該流是否支援標記。如果對某些可預知的資料不感興趣,可以使用 long skip(long n) 來調過一些流中的一些資料。
使用完流,無論是輸入還是輸出流,都要呼叫其 close() 方法對其進行關閉。
裝飾器模式
裝飾器模式(Decorator Pattern)允許向一個現有的物件新增新的功能,同時又不改變其結構。這種型別的設計模式屬於結構型模式,它是作為現有的類的一個包裝。
這種設計模式建立了一個裝飾類,用來包裝原有的類,並在保持類方法簽名完整性的前提下,提供了額外的功能。
以InputStream為例,它是一個抽象類:
public abstract class InputStream implements Closeable { ... ... }
並定義有抽象方法
public abstract int read() throws IOException;
該抽象方法由具體的子類去實現,通過InputStream的族譜圖可以看到,直接繼承了InputStream,並且提供某一特定功能的子類有:
- ByteArrayInputStream
- FileInputStream
- ObjectInputStream
- PipedInputStream
- SequenceInputStream
- StringBufferInputStream
這些子類都具有特定的功能,比如說,FileInputStream代表一個檔案輸入流並提供讀取檔案內容的功能,ObjectInputStream提供了物件反序列化的功能。
InputStream這個抽象類有一個子類與上述其它子類非常不同,這個子類就是 FilterInputStream ,可參見上圖中的InputStream族譜圖。
翻開FilterInputStream的程式碼,我們可以看到,它內部又維護了一個InputStream的成員物件,並且它的所有方法,都是呼叫這個成員物件的同名方法。換句話說,FilterInputStream它什麼事都不做。就是把呼叫委託給內部的InputStream成員物件。如下所示:
public class FilterInputStream extends InputStream { protected volatile InputStream in; protected FilterInputStream(InputStream in) { this.in = in; } public int read() throws IOException { return in.read(); } public int read(byte b[]) throws IOException { return read(b, 0, b.length); } public int read(byte b[], int off, int len) throws IOException { return in.read(b, off, len); } public long skip(long n) throws IOException { return in.skip(n); } public int available() throws IOException { return in.available(); } public void close() throws IOException { in.close(); } public synchronized void mark(int readlimit) { in.mark(readlimit); } public synchronized void reset() throws IOException { in.reset(); } public boolean markSupported() { return in.markSupported(); }
FilterInputStream的又有其子類,分別是:
- BufferedInputStream
- DataInputStream
- LineNumberInputStream
- PushbackInputStream
雖然從上面程式碼看FilterInputStream並沒有做什麼有卵用的事,但是它的子類可不同了,以BufferedInputStream為例,這個類提供了提前讀取資料的功能,也就是緩衝的功能。可以看看它的read方法:
public synchronized int read() throws IOException { if (pos >= count) { fill(); if (pos >= count) return -1; } return getBufIfOpen()[pos++] & 0xff; }
可以看到,當pos>=count時,意即需要提前緩衝一些資料的時候到了,那麼就會呼叫fill()將緩衝區加滿,以便後續讀取。 由於本文只討論io流的裝飾器模式,所以關於具體實現細節將不會展開討論,比如本文不會討論fill()方法是如何實現的,在這裡可以先將它當做一個黑盒子。
從這裡可以開始感受到,BufferedInputStream就是一個裝飾者,它能為一個原本沒有緩衝功能的InputStream新增上緩衝的功能。
比如我們常用的FileInputStream,它並沒有緩衝功能,我們每次呼叫read,都會向作業系統發起呼叫索要資料。假如我們通過BufferedInputStream來 裝飾 它,那麼每次呼叫read,會預先向作業系統多拿一些資料,這樣就不知不覺中提高了程式的效能。如以下程式碼所示:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("/home/user/abc.txt")));
同理,對於其它的FilterInputStream的子類,其作用也是一樣的,那就是裝飾一個InputStream,為它新增它原本不具有的功能。OutputStream以及家屬對於裝飾器模式的體現,也以此類推。
JDK中的io流的設計是設計模式中裝飾器模式的一個經典示範,如果細心發現,JDK中還有許多其它設計模式的體現,比如說監聽者模式等等。
相關文章
- Java IO流之裝飾模式與介面卡模式講解Java模式
- 設計模式-裝飾模式概述和使用-IO流設計模式
- java設計模式--裝飾器模式Java設計模式
- Java設計模式系列-裝飾器模式Java設計模式
- Java 設計模式(五)《裝飾器模式》Java設計模式
- java設計模式之裝飾器模式Java設計模式
- java設計模式-裝飾器模式(Decorator)Java設計模式
- Java設計模式12:裝飾器模式Java設計模式
- Java學設計模式之裝飾器模式Java設計模式
- 裝飾器模式(Decorator)模式
- 設計模式----裝飾器模式設計模式
- 設計模式-裝飾器模式設計模式
- [設計模式] 裝飾器模式設計模式
- 設計模式(九)——裝飾者模式(io原始碼分析)設計模式原始碼
- Java的IO流Java
- Python裝飾器模式Python模式
- 第53節:Java當中的IO流(上)Java
- 設計模式(八)裝飾器模式設計模式
- 設計模式之-裝飾器模式設計模式
- 設計模式之【裝飾器模式】設計模式
- 設計模式(六):裝飾器模式設計模式
- java -IO流Java
- Java IO流Java
- java - IO流Java
- Java IO流Java
- Java IO: 流Java
- Java——IO流Java
- Java設計模式(3)-裝飾者模式Java設計模式
- Java設計模式之裝飾者模式Java設計模式
- 結構型-裝飾器模式模式
- JavaDecoratorPattern(裝飾器模式)Java模式
- 原始碼中的設計模式--裝飾器模式原始碼設計模式
- Go 設計模式之裝飾器模式Go設計模式
- PHP設計模式- Decorator 裝飾器模式PHP設計模式
- Python設計模式-裝飾器模式Python設計模式
- [java IO流]之 IO概述Java
- JAVA設計模式之 裝飾模式【Decorator Pattern】Java設計模式
- Java設計模式之裝飾模式趣談Java設計模式