技術中(zhōng)心

這裏象征着我(wǒ)(wǒ)們的态度和能力

Java I/O庫的兩個設計模式
發布者:admin    信息來源:本站原創    發布時間:2015-12-04      浏覽次數:5802
分(fēn)享到:

Java I/O庫的兩個設計模式:

Java的I/O庫總體(tǐ)設計是符合裝飾者模式(Decorator)跟适配器模式(Adapter)的。如前所述,這個庫中(zhōng)處理流的類叫做流類。引子裏所談到的 FileInputStream,FileOutputStream,DataInputStream及DataOutputStream都是流處理器的例子。

1 裝飾者模式:在由 InputStream,OutputStream,Reader和Writer代表的等級結構内部,有一(yī)些流處理器可以對另一(yī)些流處理器起到裝飾作用,形成新的,具有改善了的功能的流處理器。裝飾者模式是Java I/O庫的整體(tǐ)設計模式。這樣的一(yī)個原則是符合裝飾者模式的。

2 适配器模式:在由InputStream,OutputStream,Reader和Writer代表的等級結構内部,有一(yī)些流處理器是對其它類型的流源的适配。這就是适配器模式的應用。

适配器模式應用到了原始流處理器的設計上面,構成了I/O庫所有流處理器的起點。

JDK爲程序員(yuán)提供了大(dà)量的類庫,而爲了保持類庫的可重用性,可擴展性和靈活性,其中(zhōng)使用到了大(dà)量的設計模式,本文将介紹JDK的I/O包中(zhōng)使用到的Decorator模式,并運用此模式,實現一(yī)個新的輸出流類。

Decorator模式簡介

Decorator模式又(yòu)名包裝器(Wrapper),它的主要用途在于給一(yī)個對象動态的添加一(yī)些額外(wài)的職責。與生(shēng)成子類相比,它更具有靈活性。

有時候,我(wǒ)(wǒ)們需要爲一(yī)個對象而不是整個類添加一(yī)些新的功能,比如,給一(yī)個文本區添加一(yī)個滾動條的功能。我(wǒ)(wǒ)們可以使用繼承機制來實現這一(yī)功能,但是這種方法不夠靈活,我(wǒ)(wǒ)們無法控制文本區加滾動條的方式和時機。而且當文本區需要添加更多的功能時,比如邊框等,需要創建新的類,而當需要組合使用這些功能時無疑将會引起類的爆炸。

我(wǒ)(wǒ)們可以使用一(yī)種更爲靈活的方法,就是把文本區嵌入到滾動條中(zhōng)。而這個滾動條的類就相當于對文本區的一(yī)個裝飾。這個裝飾(滾動條)必須與被裝飾的組件(文本區)繼承自同一(yī)個接口,這樣,用戶就不必關心裝飾的實現,因爲這對他們來說是透明的。裝飾會将用戶的請求轉發給相應的組件(即調用相關的方法),并可能在轉發的前後做一(yī)些額外(wài)的動作(如添加滾動條)。通過這種方法,我(wǒ)(wǒ)們可以根據組合對文本區嵌套不同的裝飾,從而添加任意多的功能。這種動态的對對象添加功能的方法不會引起類的爆炸,也具有了更多的靈活性。

以上的方法就是Decorator模式,它通過給對象添加裝飾來動态的添加新的功能。

Component爲組件和裝飾的公共父類,它定義了子類必須實現的方法。

ConcreteComponent是一(yī)個具體(tǐ)的組件類,可以通過給它添加裝飾來增加新的功能。

Decorator是所有裝飾的公共父類,它定義了所有裝飾必須實現的方法,同時,它還保存了一(yī)個對于Component的引用,以便将用戶的請求轉發給Component,并可能在轉發請求前後執行一(yī)些附加的動作。

ConcreteDecoratorA和ConcreteDecoratorB是具體(tǐ)的裝飾,可以使用它們來裝飾具體(tǐ)的Component.

JAVA IO包中(zhōng)的Decorator模式

JDK提供的java.io包中(zhōng)使用了Decorator模式來實現對各種輸入輸出流的封裝。以下(xià)将以java.io.OutputStream及其子類爲例,讨論一(yī)下(xià)Decorator模式在IO中(zhōng)的使用。

首先來看一(yī)段用來創建IO流的代碼:

以下(xià)是代碼片段:

try {

OutputStream out = new DataOutputStream(new FileOutputStream("test.txt"));

} catch (FileNotFoundException e) {

e.printStackTrace();

}

這段代碼對于使用過JAVA輸入輸出流的人來說再熟悉不過了,我(wǒ)(wǒ)們使用 DataOutputStream封裝了一(yī)個FileOutputStream.這是一(yī)個典型的Decorator模式的使用,FileOutputStream相當于Component,DataOutputStream就是一(yī)個Decorator.将代碼改成如下(xià),将會更容易理解:

以下(xià)是代碼片段:

try {

OutputStream out = new FileOutputStream("test.txt");

out = new DataOutputStream(out);

} catch(FileNotFoundException e) {

e.printStatckTrace();

}

由于FileOutputStream和DataOutputStream有公共的父類OutputStream,因此對對象的裝飾對于用戶來說幾乎是透明的。下(xià)面就來看看OutputStream及其子類是如何構成Decorator模式的:

OutputStream是一(yī)個抽象類,它是所有輸出流的公共父類,其源代碼如下(xià):

以下(xià)是代碼片段:

public abstract class OutputStream implements Closeable, Flushable {

public abstract void write(int b) throws IOException;

……

}

它定義了write(int b)的抽象方法。這相當于Decorator模式中(zhōng)的Component類。

ByteArrayOutputStream,FileOutputStream 和 PipedOutputStream 三個類都直接從OutputStream繼承,以ByteArrayOutputStream爲例:

以下(xià)是代碼片段:

public class ByteArrayOutputStream extends OutputStream {

protected byte buf[];

protected int count;

public ByteArrayOutputStream() {

this(32);

}

public ByteArrayOutputStream(int size) {

if (size 〈 0) {

throw new IllegalArgumentException("Negative initial size: "

+ size);

}

buf = new byte[size];

}

public synchronized void write(int b) {

int newcount = count + 1;

if (newcount 〉 buf.length) {

byte newbuf[] = new byte[Math.max(buf.length 〈〈 1, newcount)];

System.arraycopy(buf, 0, newbuf, 0, count);

buf = newbuf;

}

buf[count] = (byte)b;

count = newcount;

}

……

}

它實現了OutputStream中(zhōng)的write(int b)方法,因此我(wǒ)(wǒ)們可以用來創建輸出流的對象,并完成特定格式的輸出。它相當于Decorator模式中(zhōng)的ConcreteComponent類。

接着來看一(yī)下(xià)FilterOutputStream,代碼如下(xià):

以下(xià)是代碼片段:

public class FilterOutputStream extends OutputStream {

protected OutputStream out;

public FilterOutputStream(OutputStream out) {

this.out = out;

}

public void write(int b) throws IOException {

out.write(b);

}

……

}

同樣,它也是從OutputStream繼承。但是,它的構造函數很特别,需要傳遞一(yī)個OutputStream的引用給它,并且它将保存對此對象的引用。而如果沒有具體(tǐ)的OutputStream對象存在,我(wǒ)(wǒ)們将無法創建 FilterOutputStream.由于out既可以是指向FilterOutputStream類型的引用,也可以是指向 ByteArrayOutputStream等具體(tǐ)輸出流類的引用,因此使用多層嵌套的方式,我(wǒ)(wǒ)們可以爲ByteArrayOutputStream添加多種裝飾。這個FilterOutputStream類相當于Decorator模式中(zhōng)的Decorator類,它的write(int b)方法隻是簡單的調用了傳入的流的write(int b)方法,而沒有做更多的處理,因此它本質上沒有對流進行裝飾,所以繼承它的子類必須覆蓋此方法,以達到裝飾的目的。

BufferedOutputStream 和 DataOutputStream是FilterOutputStream的兩個子類,它們相當于Decorator模式中(zhōng)的 ConcreteDecorator,并對傳入的輸出流做了不同的裝飾。以BufferedOutputStream類爲例:

以下(xià)是代碼片段:

public class BufferedOutputStream extends FilterOutputStream {

……

private void flushBuffer() throws IOException {

if (count 〉 0) {

out.write(buf, 0, count);

count = 0;

}

}

public synchronized void write(int b) throws IOException {

if (count 〉= buf.length) {

flushBuffer();

}

buf[count++] = (byte)b;

}

……

}

這個類提供了一(yī)個緩存機制,等到緩存的容量達到一(yī)定的字節數時才寫入輸出流。首先它繼承了FilterOutputStream,并且覆蓋了父類的write(int b)方法,在調用輸出流寫出數據前都會檢查緩存是否已滿,如果未滿,則不寫。這樣就實現了對輸出流對象動态的添加新功能的目的。

總 結

在java.io包中(zhōng),不僅OutputStream用到了Decorator設計模式,InputStream,Reader,Writer等都用到了此模式。而作爲一(yī)個靈活的,可擴展的類庫,JDK中(zhōng)使用了大(dà)量的設計模式,比如在 Swing包中(zhōng)的MVC模式,RMI中(zhōng)的Proxy模式等等。對于JDK中(zhōng)模式的研究不僅能加深對于模式的理解,而且還有利于更透徹的了解類庫的結構和組成。

4000-880-989
(24小(xiǎo)時熱線)
聯系客服
微信公衆号

官方公衆号

小(xiǎo)程序

©2008-2022 CORPORATION ALL Rights Reserved. 西山區唯美網絡科技工作室版權所有 滇公網安備