java io
在java語言 I/O庫的設(shè)計(jì)中,使用了兩個(gè)結(jié)構(gòu)模式,即裝飾模式和適配器模式。在任何一種計(jì)算機(jī)語言中,輸入/輸出都是一個(gè)很重要的部分。與一般的計(jì)算機(jī)語言相比,java將輸入/輸出的功能和使用范疇做了很大的擴(kuò)充。因此輸入輸出在java語言中占有極為重要的位置。
java語言采用流的機(jī)制來實(shí)現(xiàn)輸入/輸出。所謂流,就是數(shù)據(jù)的有序排列,流可以是從某個(gè)源(稱為流源,或者 Source of Stream)出來,到某個(gè)目的(Sink of Stream)地去。根據(jù)流的方向可以將流分成輸出流和輸入流。程序通過輸入流讀取數(shù)據(jù),想輸出流寫出數(shù)據(jù)。
例如:一個(gè)java程序可以使用FileInputStream類從一個(gè)磁盤文件讀取數(shù)據(jù),如下圖:

像FileInputStream這樣的處理器叫流處理器。一個(gè)流處理器就像一個(gè)流的管道一樣,從一個(gè)流源吸入某種類型的數(shù)據(jù),并輸出某種類型的數(shù)據(jù)。上面的示意圖叫流的管道圖。
類似地,也可以用FileOutputStream類向一個(gè)磁盤文件寫數(shù)據(jù),如下圖:

在實(shí)際的應(yīng)用當(dāng)中,這樣簡單的機(jī)制并沒有太大的用處。程序需要寫出的往往是非常結(jié)構(gòu)話的信息,因此這些Byte類型的數(shù)據(jù)實(shí)際上是一些數(shù)字、文字、源代碼等。java的I/O庫提供了一個(gè)稱作鏈接(Chaining)的機(jī)制,可以將一個(gè)流處理器與另一個(gè)流處理器首尾相接,以其中之一的輸出為輸入,形成一個(gè)流管道的鏈接。
例如,DateInputStream流處理器可以把FileInputStream流對象的輸出當(dāng)做輸入,將Byte類型的數(shù)據(jù)轉(zhuǎn)換成java的原始數(shù)據(jù)類型和String數(shù)據(jù)類型,如下圖:

類似地,向一個(gè)文件中寫入Byte類型的數(shù)據(jù)也不是一個(gè)簡單的過程。一個(gè)程序需要向一個(gè)文件里寫入的數(shù)據(jù)往往是結(jié)構(gòu)化的,而Byte類型則是原始的類型,因此,在寫入的時(shí)候必須首先經(jīng)過轉(zhuǎn)換。DateOutputStream流處理器提供了接受原始數(shù)據(jù)類型和String數(shù)據(jù)類型的方法,而這個(gè)流處理器的輸出數(shù)據(jù)則是Byte類型。換而言之,DateOutputStream可以將源數(shù)據(jù)轉(zhuǎn)換成Byte類型的數(shù)據(jù),在輸出出來。
這樣一來,就可以將DateOutputStream與FileOutputStream鏈接起來。這樣做的結(jié)果就是,程序可以將原始數(shù)據(jù)類型和String數(shù)據(jù)類型的源數(shù)據(jù)寫到這個(gè)鏈接好的雙重管道里面,達(dá)到將結(jié)構(gòu)話數(shù)據(jù)寫到磁盤文件里的目的,如下圖所示:

這是鏈接的威力。
流處理器所處理的流必定都有流源,如果將流類所處理的流源分類的話,那么基本可以分成兩大類:
(1)數(shù)組、String、File等,這一種叫原始流源。
(2)同樣類型的流用做鏈接流類的流源,就叫做鏈接流源。
java I/O庫的設(shè)計(jì)原則
java語言的I/O庫是對各種常見的流源、流匯以及處理過程的抽象化。客戶端的java 程序不必知道最終的的流源、流匯是磁盤上的文件還是一個(gè)數(shù)組,或者是一個(gè)線程;也不比插手到諸如數(shù)據(jù)是否緩存、可否按照行號讀取等處理的細(xì)節(jié)中去。
要理解java I/O 這個(gè)龐大而復(fù)雜的庫,關(guān)鍵是掌握兩個(gè)對稱性和兩個(gè)設(shè)計(jì)模式。
java I/O庫的兩個(gè)對稱性
java I/O庫具有兩個(gè)對稱性,它們分別是:
(1)輸入-輸出對稱:比如InputStream 和OutputStream 各自占據(jù)Byte流的輸入和輸出的兩個(gè)平行的等級結(jié)構(gòu)的根部;而Reader和Writer各自占據(jù)Char流的輸入和輸出的兩個(gè)平行的等級結(jié)構(gòu)的根部。
(2)byte-char對稱:InputStream和Reader的子類分別負(fù)責(zé)byte和插入流的輸入;OutputStream和Writer的子類分別負(fù)責(zé)byte和Char流的輸出,它們分別形成平行的等級結(jié)構(gòu)。
java I/O庫的兩個(gè)設(shè)計(jì)模式
ava I/O庫的總體設(shè)計(jì)是符合裝飾模式和適配器模式的。如前所述,這個(gè)庫中處理流的類叫流類。
裝飾模式:在由InputStream、OutputStream、Reader和Writer代表的等級結(jié)構(gòu)內(nèi)部,有一些流處理器可以對另一些流處理器起到裝飾作用,形成新的、具有改善了的功能的流處理器。
適配器模式:在由InputStream、OutputStream、Reader和Writer代表的等級結(jié)構(gòu)內(nèi)部,有一些流處理器是對其他類型的流處理器的適配。這就是適配器的應(yīng)用。
裝飾模式的應(yīng)用
裝飾模式在java中的最著名的應(yīng)用莫過于java I/O標(biāo)準(zhǔn)庫的設(shè)計(jì)了。
由于java I/O庫需要很多性能的各種組合,如果這些性能都是用繼承來實(shí)現(xiàn),那么每一種組合都需要一個(gè)類,這樣就會造成大量行重復(fù)的類出現(xiàn)。如果采用裝飾模式,那么類的數(shù)目就會大大減少,性能的重復(fù)也可以減至最少。因此裝飾模式是java I/O庫基本模式。
裝飾模式的引進(jìn),造成靈活性和復(fù)雜性的提高。因此在使用 java I/O 庫時(shí),必須理解java I/O庫是由一些基本的原始流處理器和圍繞它們的裝飾流處理器所組成的。
InputStream類型中的裝飾模式
InputStream有七個(gè)直接的具體子類,有四個(gè)屬于FilterInputStream的具體子類,如下圖所示:

上圖中所有的類都叫做流處理器,這個(gè)圖叫做(InputStream類型)流處理器圖。根據(jù)輸入流的源的類型,可以將這些流分為兩種,即原始流類和鏈接流處理器。
原始流處理器
原始流處理器接收一個(gè)Byte數(shù)組對象、String對象、FileDescriptor對象或者不同類型的流源對象(就是前面所說的原始流源),并生成一個(gè)InputStream類型的流對象。在InputStream類型的流處理器中,原始流處理器包括以下四種:
(1)ByteArrayInputStream:為多線程的通訊提供緩沖區(qū)操作工作,接受一個(gè)Byte數(shù)組作為流的源。
(2)FileInputStream:建立一個(gè)與文件有關(guān)的輸入流。接受一個(gè)File對象作為流的源。
(3)PipedInputStream:可以和PipedOutputStream配合使用,用于讀入一個(gè)數(shù)據(jù)管道的數(shù)據(jù)。接受一個(gè)PipedOutputStream作為源。
(4)StringBufferInputStream:將一個(gè)字符串緩沖區(qū)抓換為一個(gè)輸入流。接受一個(gè)String對象作為流的源。
與原始流處理器相對應(yīng)的是鏈接流處理器。
鏈接流處理器
所謂鏈接流處理器就是可以接受另一個(gè)(同種類的)流對象(就是鏈接流源)作為流源,并對之進(jìn)行功能擴(kuò)展的類。InputStream類型的鏈接流處理器包括以下幾種,它們接受另一個(gè)InputStream對象作為流源。
(1)FilterInputStream稱為過濾輸入流,它將另一個(gè)輸入流作為流源。這個(gè)類的子類包括以下幾種:
BufferInputStream:用來從硬盤將數(shù)據(jù)讀入到一個(gè)內(nèi)存緩沖區(qū)中,并從此緩沖區(qū)提供數(shù)據(jù)。
DateInputStream:提供基于多字節(jié)的讀取方法,可以讀取原始數(shù)據(jù)類型的數(shù)據(jù)。
LineNumberInputStream:提供帶有行計(jì)算功能的過濾輸入流。
PushbackInputStream: 提供特殊的功能,可以將已讀取的直接“推回”輸入流中。
(2)ObjectInputStream 可以將使用ObjectInputStream串行化的原始數(shù)據(jù)類型和對象重新并行化。
(3)SequenceInputStream可以將兩個(gè)已有的輸入流連接起來,形成一個(gè)輸入流,從而將多個(gè)輸入流排列構(gòu)成一個(gè)輸入流序列。
必須注意的是,雖然PipedInuptStream接受一個(gè)流對象PipedOutputStream作為流的源,但是PipedOutputStream流對象的類型不是InputStream,因此PipedInputStream流處理器仍屬于原始流處理器。
抽象結(jié)構(gòu)圖

上面流處理器圖與裝飾模式的結(jié)構(gòu)圖有明顯的相同之處。實(shí)際上InputStream類型的流處理器結(jié)構(gòu)確實(shí)符合裝飾模式,而這可以從它們在結(jié)構(gòu)中所扮演的角色中分辯出來。
裝飾模式的各個(gè)角色
在所有InputStream類型的鏈接流處理其中,使用頻率最大的就是FilterInputStream類,以這個(gè)類為抽象裝飾角色的裝飾模式結(jié)構(gòu)非常明顯和典型。以這個(gè)類為核心說明裝飾模式的各個(gè)角色是由哪些流處理器扮演:
抽象構(gòu)件(Component)角色:由InputStream扮演。這是一個(gè)抽象類,為各種子類型處理器提供統(tǒng)一的接口。
具體構(gòu)建(Concrete Component)角色:由ByteArrayInputStream、FileInputStream、PipedInputStream以及StringBufferInputStream等原始流處理器扮演。它們實(shí)現(xiàn)了抽象構(gòu)建角色所規(guī)定的接口,可以被鏈接流處理器所裝飾。
抽象裝飾(Decorator)角色:由FilterInputStream扮演。它實(shí)現(xiàn)了InputStream所規(guī)定的接口。
具體裝飾(Concrete Decorator)角色:由幾個(gè)類扮演,分別是DateInputStream、BufferedInputStream 以及兩個(gè)不常用到的類LineNumberInputStream和PushbackInputStream。
鏈接流其實(shí)就是裝飾角色,原始流就是具體構(gòu)建角色,如下圖所示:

一方面,鏈接流對象接受一個(gè)(同類型的)原始流對象或者另一個(gè)(同類型的)鏈接流對象作為流源;另一方面,它們都對流源對象的內(nèi)部工作方法做了相應(yīng)的改變,這種改變是裝飾模式所要達(dá)到的目的。比如:
(1)BufferedInputStream “裝飾” 了InputStream的內(nèi)部工作方式,使得流的讀入操作使用緩沖機(jī)制。在使用了緩沖機(jī)制后,不會對每一次的流讀入操作都產(chǎn)生一個(gè)物理的讀盤動作,從而提高了程序的效率。在涉及到物理流的讀入時(shí),都應(yīng)當(dāng)使用這個(gè)裝飾流類。
(2)LineNumberInputStream和PushbackInputStream也同樣“裝飾”了InputStream的內(nèi)部工作方式,前者使得程序能夠按照行號讀入數(shù)據(jù);后者能使程序在讀入的過程中退后一個(gè)字符。后兩個(gè)裝飾類可能在實(shí)際的編程工作中很少用到,因?yàn)樗鼈兪菫榱酥С钟胘ava語言做編譯器而準(zhǔn)備的。
(3)DateInputStream子類讀入各種不同的原始數(shù)據(jù)類型以及String類型的數(shù)據(jù),這一點(diǎn)可以從它提供的各種read()方法看出來:readByte()、readUnsignedByte()、readShort()、readUnsignedShort()、readChar()、readInt()、readLong()、readFloat()、readDouble()、readUTF()。使用這個(gè)流處理器以及它的搭檔DateOutputStream,可以將原始數(shù)據(jù)通過流從一個(gè)地方移到另一個(gè)地方。
OutputStream 類型中的裝飾模式
outputStream是一個(gè)用于輸出的抽象類,它的接口、子類的等級結(jié)構(gòu)、子類的功能都和InputStream有很好的對稱性。在OutputStream給出的接口里,將write換成read就得到了InputStream的接口,而其具體子類則在功能上面是平行的。
(1)針對byte數(shù)字流源的鏈接流類,以ByteArrayInputStream描述輸入流,以ByteArrayOutputStream描述輸出流。
(2)針對String流源的鏈接流類,以StringBufferInputStream描述輸入流,以StringBufferOutputStream描述輸出流。
(3)針對文件流源的鏈接流類,以FileInputStream描述輸入流,以FileOutputStream描述輸出流。
(4)針對數(shù)據(jù)管道流源的鏈接流類,以PipedInputStream描述輸入流,以PipedOutputStream描述輸出流。
(5)針對以多個(gè)流組成的序列,以SequenceInputStream描述輸入流,以SequenceOutputStream描述輸出流。
OutputStream類型有哪些子類
outputStream有5個(gè)直接的具體子類,加上三個(gè)屬于FilterInputStream的具體子類,一共有8個(gè)具體子類,如下圖:

原始流處理器
在OutputStream類型的流處理器中,原始流處理器包括以下三種:
ByteArrayOutputStream:為多線程的通信提供緩沖區(qū)操作功能。輸出流的匯集是一個(gè)byte數(shù)組。
FileOutputStream:建立一個(gè)與文件有關(guān)的輸出流。輸出流的匯集是一個(gè)文件對象。
PipedOutputStream: 可以與PipedInputStream配合使用,用于向一個(gè)數(shù)據(jù)管道輸出數(shù)據(jù)。
鏈接流處理器
OutputStream類型的鏈接流處理器包括以下幾種:
(1)FilterOutputStream:稱為過濾輸出流,它將另一個(gè)輸出流作為流匯。這個(gè)類的子類有如下幾種:
BufferedOutputStream:用來向一個(gè)內(nèi)存緩沖區(qū)中寫數(shù)據(jù),并將此緩沖區(qū)的數(shù)據(jù)輸入到硬盤中。
DataOutputStream:提供基于多字節(jié)的寫出方法,可以寫出原始數(shù)據(jù)類型的數(shù)據(jù)。
PrintStream:用于產(chǎn)生格式化輸出。System.out 靜態(tài)對象就是一個(gè)PrintStream。
(2)ObjectOutputStream 可以將原始數(shù)據(jù)類型和對象串行化。
裝飾模式的各個(gè)角色
在所有的鏈接流處理器中,最常見的就是FilterOutputStream類。以這個(gè)類為核心的裝飾模式結(jié)構(gòu)非常明顯和典型,如下圖:

裝飾模式所涉及的各個(gè)角色:
抽象構(gòu)件(Component)角色:由OutputStream扮演,這是一個(gè)抽象類,為各種的子類型流處理器提供統(tǒng)一的接口。
具體構(gòu)件(Concrete Component)角色:由ByteArrayOutputStream、FileOutputStream、PipedOutputStream等扮演,它們均實(shí)現(xiàn)了OutputStream所聲明的接口。
抽象裝飾(Decorator)角色:由FilterOutputStream扮演,它與OutputStream有相同的接口,而這正是裝飾類的關(guān)鍵。
具體裝飾(Concrete Decorator)角色:由幾個(gè)類扮演,分別是BufferedOutputStream、DateOutputStream、以及PrintStream。
所謂鏈接流,就是裝飾模式中的裝飾角色,原始流就是具體構(gòu)件角色。
與DateInputStream相對應(yīng)的是DataOutputStream,后者負(fù)責(zé)將由原始數(shù)據(jù)類型和String對象組成的數(shù)據(jù)格式化,并輸出到一個(gè)流中,使得任何機(jī)器上的任何DataInputStream類型的對象都可以讀入這些數(shù)據(jù)。所有的方法都是以write開始。
如果需要對數(shù)據(jù)進(jìn)行真正的格式化,以便輸出到像控制臺顯示那樣,那就需要使用PrintStream。
PrintStream可以對由原始數(shù)據(jù)類型和String對象組成的數(shù)據(jù)進(jìn)行格式化,以形成可以閱讀的格式;而DataOutputStream則不同,它將數(shù)據(jù)輸出到一個(gè)流中,以便DataInputStream可以在任何機(jī)器而后操作系統(tǒng)中都可以重新將數(shù)據(jù)讀入,并進(jìn)行結(jié)構(gòu)重建。
PrintStream對象最重要的兩個(gè)方法是print() 和println(),這兩個(gè)方法都是重載的,以便可以打印出所有使用類型的數(shù)據(jù)。這兩個(gè)方法之間的區(qū)別是后者每行結(jié)束時(shí)多打印出一個(gè)換行符號。
BufferedOutputStream對一個(gè)輸出流進(jìn)行裝飾,使得流的寫出操作使用緩沖機(jī)制。在使用緩沖機(jī)制后,不會對每一次的流的寫入操作都產(chǎn)生一個(gè)物理的寫動作,從而提高的程序的效率。在涉及到物理流的地方,比如控制臺I/O、文件I/O等,都應(yīng)當(dāng)使用這個(gè)裝飾流處理器。
Reader類型中的裝飾模式
在Reader類型的流處理器中,原始流處理器包括以下四種:
(1)CharArrayReader:為多線程的通信提供緩沖區(qū)操作功能。
(2)InputStreamReader:這個(gè)類有一個(gè)子類--FileReader。
(3)PipedReader:可以與PipedOutputStream配合使用,用于讀入一個(gè)數(shù)據(jù)管道的數(shù)據(jù)。
(4)StringReader:建立一個(gè)與文件有關(guān)的輸入流。
鏈接流處理器包括以下:
(1)BufferedReader:用來從硬盤將數(shù)據(jù)讀入到一個(gè)內(nèi)存緩沖區(qū),并從此緩沖區(qū)提供數(shù)據(jù),這個(gè)類的子類為LineNumberReader。
(2)FilterReader:成為過濾輸入流,它將另一個(gè)輸入流作為流的來源。這個(gè)類的子類有PushbackReader,提供基于多字節(jié)的讀取方法,可以讀取原始數(shù)據(jù)類型的數(shù)據(jù),Reader類型的類圖如下所示:

Reader類型中,裝飾模式所涉及的各個(gè)角色:
(1)抽象構(gòu)建(Component)角色:有Reader扮演。這是一個(gè)抽象類,為各種的子類型流處理器提供統(tǒng)一的接口。
(2)具體構(gòu)建(Concrete Component)角色:由CharArrayReader、InputStreamReader、PiPedReader、StringReader等扮演,他們均實(shí)現(xiàn)了Reader所聲明的接口。
(3)抽象裝飾(Decorator)角色:由BufferedReader和FilterReader扮演。這兩者有著與Reader相同的接口,它們分別給出兩個(gè)裝飾角色的等級結(jié)構(gòu),第一個(gè)給出LineNumberReader作為具體裝飾角色,另一個(gè)給出PushbackReader 作為具體裝飾角色。
(4)具體裝飾(Concrete Decorator)角色:LineNumberReader作為BufferedReader的具體裝飾角色,BufferedReader作為FilterReader的具體裝飾角色。
如下圖所示,標(biāo)有聚合連線的就是抽象裝飾角色:

Writer類型中的裝飾模式
Writer類型是一個(gè)與Reader類型平行的等級結(jié)構(gòu),而且Writer類型的等級結(jié)構(gòu)幾乎與Reader的等級結(jié)構(gòu)關(guān)于輸入/輸出是對稱的。如圖所示:

在Writer類型的流處理器中,原始流處理器包括以下四種:
(1)CharArrayWriter:為多線程的通信提供緩沖區(qū)的操作功能。
(2)OutputStreamWriter:建立一個(gè)與文件有關(guān)的輸出流。含有一個(gè)具體子類FileWrite,為Write類型的輸出流提供文件輸出功能。
(3)PipedWriter:可以和PipedOutputStream配合使用,用于讀如果一個(gè)數(shù)據(jù)管道的數(shù)據(jù)。
(4)StringWriter:想一個(gè)StringBuffer寫出數(shù)據(jù)。
鏈接流處理器包括以下三種:
(1)BufferedWriter:為Writer類型的流處理器提供緩沖區(qū)功能。
(2)FilterWriter:稱為過濾輸入流,它將另一個(gè)輸入流作為流的來源。這是一個(gè)沒有子類的抽象類。
(3)PrintWriter:支持格式化的文字輸出。
Writer類型中,裝飾模式所涉及的各個(gè)角色:
(1)抽象構(gòu)建(Component)角色:由Write扮演。這是一個(gè)抽象類,為為各種子類型的流處理器提供統(tǒng)一的接口。
(2)具體構(gòu)建(Concrete Component):角色由CharArrayWriter、OutputStreamWriter、
PipedWriter、StringWriter扮演,它們實(shí)現(xiàn)了Writer所聲明的接口。
(3)抽象裝飾(Decorator)角色:由BufferedWriter、FilterWriter、PrintWriter扮演,它們有著與Write
相同的接口。
(4)具體裝飾(Concrete Decorator)角色:與抽象裝飾角色合并。
如下圖所示,標(biāo)出了從抽象裝飾角色到抽象構(gòu)件角色的聚合連線,更易于與裝飾模式的結(jié)構(gòu)圖比較。

適配器模式的應(yīng)用
適配器模式是java I/O庫中第二個(gè)最重要的設(shè)計(jì)模式。
InputStream原始流處理器中的適配器模式
InputStream類型的原始流處理器是適配器模式的應(yīng)用。
ByteArrayInputStream是一個(gè)適配器類
ByteArrayInputStream繼承了InputStream的接口,而封裝了一個(gè)byte數(shù)組。換而言之,它將一個(gè)byte數(shù)組的接口適配成了InputStream流處理器的接口。
java語言支持四種類型:java類、java接口、java數(shù)組和原始類型。前三章是引用類型,類和數(shù)組的實(shí)例都是對象,原始類型的值不少對象。java語言的數(shù)組是像所有其他對象一樣的對象,而不管數(shù)組中所存放的元素的類型是什么。這樣一來,ByteArrayInputStream就符合適配器模式的描述,而且是一個(gè)對象形式的適配器類。如下圖所示:

StringBufferInputStream是一個(gè)適配器類
StringBufferInputStream繼承了InputStream類型,同時(shí)持有一個(gè)對String類型的引用。這是將String對象適配成InputStream類型的對象形式的適配器模式,如下圖:

OutputStream原始流處理器中的適配器模式
在OutputStream類型中,所有的原始流處理器都是適配器類。
ByteArrayOutputStream是一個(gè)適配器類
ByteArrayOutputStream繼承了OutputStream類型,同事持有一個(gè)對byte數(shù)組的引用。它把一個(gè)byte數(shù)組的接口適配成OutputStream類型的接口,因此也是一個(gè)對象類型的適配器模式的應(yīng)用。如下圖:

FileOutputStream是一個(gè)適配器類
FileOutputStream繼承OutputStream,同時(shí)持有一個(gè)對FileDescriptor對象的引用。這是一個(gè)將FileDescriptor適配成OutputStream接口的對象形式的適配器模式,如下圖所示:

PipedOutputStream是一個(gè)適配器類
PipedOutputStream總是和PipedInputStream一起使用,它接收一個(gè)類型為PipedInputStream的輸入類型,并將之轉(zhuǎn)換成OutputStream類型的輸出流,這是一個(gè)對象形式的適配器模式應(yīng)用。如下圖:

Reader原始流處理器中的適配器模式
Reader 類型的原始流處理器都是適配器模式的應(yīng)用。
CharArrayReader是一個(gè)適配器類。
CharArrayReader將一個(gè)Char數(shù)組適配成Reader類型的輸入流,因此它是一個(gè)對象形式的適配器應(yīng)用,如下圖所示:

StringReader是一個(gè)適配器類
StringReader 繼承了Reader類型,持有一個(gè)對String類型的引用。它將String的接口適配成Reader類型的接口,如下圖所示:

Writer類型中的適配器模式
Writer類型中的原始流處理器就是適配器模式的具體應(yīng)用。
CharArrayWriter是一個(gè)適配器類。
CharArrayWriter將一個(gè)Char數(shù)組適配成Writer 接口,如下圖所示:

PipedWriter是一個(gè)適配器類
PipedWriter總是與PiPedReader一同使用,它將一個(gè)PipedReader對象的接口適配成一個(gè)Writer類型的接口,如下圖所示:

StringWriter是一個(gè)適配器類
StringWriter繼承Writer類型,同時(shí)持有一個(gè)StringBuffer對象,它將StringBuffer對象的接口適配成為了
Writer類型的接口,是一個(gè)對象形式的適配器 模式的應(yīng)用,如下圖所示:

從byte流到char流的適配
在java語言的標(biāo)準(zhǔn)庫 java I/O 里面,有一個(gè)InputStreamReader類叫做橋梁(bridge)類。InputStreamReader是從byte流到char流的一個(gè)橋梁,它讀入byte數(shù)據(jù)并根據(jù)指定的編碼將之翻譯成char數(shù)據(jù)。
InputStreamReader雖然叫“橋梁”,但它不爽橋梁模式,是適配器模式的應(yīng)用。
InputStreamReader
InputStreamReader是從byte輸入流到char輸入流的一個(gè)適配器。下圖所示就是InputStreamReader 的結(jié)構(gòu)圖:

為了說明適配器類InputStreamReader是如何使用,請看下面例子。Echo類可以將控制臺輸入的任何字符串從新打印出來,源代碼如下:
Echo.java
01 |
package com.think.cla; |
02 |
|
03 |
import java.io.BufferedReader; |
04 |
import java.io.IOException; |
05 |
import java.io.InputStreamReader; |
06 |
|
07 |
public class Echo { |
08 |
|
09 |
public static void main(String [] args) throws IOException{ |
10 |
String line; |
11 |
InputStreamReader input = new InputStreamReader(System.in); |
12 |
System.out.println( "Enter data and push enter:" ); |
13 |
BufferedReader reader = new BufferedReader(input); |
14 |
line = reader.readLine(); |
15 |
System.out.println( "Data entered :" +line); |
16 |
} |
17 |
|
18 |
} |
BufferedReader類“裝飾”它,將緩沖功能加上去。這樣一來,就可以使用BufferedReader對象的readerLine()
方法讀入整行的輸入數(shù)據(jù),數(shù)據(jù)類型是String。
在得到這個(gè)數(shù)據(jù)之后,程序又將它寫出到System.out 中去,完成了全部的流操作,下圖所示為其管道圖:

本系統(tǒng)使用了BufferedReader來為流的讀入提供緩沖功能,這樣做的直接效果是可以使用readLine()方法按行讀入數(shù)據(jù)。但是由于Reader接口并不提供readLine()方法,所以這樣一來,系統(tǒng)就必須聲明一個(gè)BufferedReader類型的流處理器,而不是一個(gè)Reader類型的流處理器,這意味著裝飾模式的退化。
在上面的管道連接過程中,InputStreamReader 起到了適配器的作用,它將一個(gè)byte類型的輸入流適配成為一個(gè)char類型的輸入流。在這之后,BufferedReader則起到了裝飾模式的作用,將緩沖機(jī)制引入到流的讀入中。因此這個(gè)例子涉及到了兩個(gè)設(shè)計(jì)模式。