<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    JAVA & XML & JAVASCRIPT & AJAX & CSS

    Web 2.0 技術(shù)儲備............

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      77 隨筆 :: 17 文章 :: 116 評論 :: 0 Trackbacks

    http://java.chinaitlab.com/model/39095.html

    JDK為程序員提供了大量的類庫,而為了保持類庫的可重用性,可擴(kuò)展性和靈活性,其中使用到了大量的設(shè)計(jì)模式,本文將介紹JDK的I/O包中使用到的Decorator模式,并運(yùn)用此模式,實(shí)現(xiàn)一個(gè)新的輸出流類。

      Decorator模式簡介

      Decorator模式又名包裝器(Wrapper),它的主要用途在于給一個(gè)對象動態(tài)的添加一些額外的職責(zé)。與生成子類相比,它更具有靈活性。
    有時(shí)候,我們需要為一個(gè)對象而不是整個(gè)類添加一些新的功能,比如,給一個(gè)文本區(qū)添加一個(gè)滾動條的功能。我們可以使用繼承機(jī)制來實(shí)現(xiàn)這一功能,但是這種方法不夠靈活,我們無法控制文本區(qū)加滾動條的方式和時(shí)機(jī)。而且當(dāng)文本區(qū)需要添加更多的功能時(shí),比如邊框等,需要創(chuàng)建新的類,而當(dāng)需要組合使用這些功能時(shí)無疑將會引起類的爆炸。

      我們可以使用一種更為靈活的方法,就是把文本區(qū)嵌入到滾動條中。而這個(gè)滾動條的類就相當(dāng)于對文本區(qū)的一個(gè)裝飾。這個(gè)裝飾(滾動條)必須與被裝飾的組件(文本區(qū))繼承自同一個(gè)接口,這樣,用戶就不必關(guān)心裝飾的實(shí)現(xiàn),因?yàn)檫@對他們來說是透明的。裝飾會將用戶的請求轉(zhuǎn)發(fā)給相應(yīng)的組件(即調(diào)用相關(guān)的方法),并可能在轉(zhuǎn)發(fā)的前后做一些額外的動作(如添加滾動條)。通過這種方法,我們可以根據(jù)組合對文本區(qū)嵌套不同的裝飾,從而添加任意多的功能。這種動態(tài)的對對象添加功能的方法不會引起類的爆炸,也具有了更多的靈活性。

      以上的方法就是Decorator模式,它通過給對象添加裝飾來動態(tài)的添加新的功能。如下是Decorator模式的UML圖:


      Component為組件和裝飾的公共父類,它定義了子類必須實(shí)現(xiàn)的方法。

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

      Decorator是所有裝飾的公共父類,它定義了所有裝飾必須實(shí)現(xiàn)的方法,同時(shí),它還保存了一個(gè)對于Component的引用,以便將用戶的請求轉(zhuǎn)發(fā)給Component,并可能在轉(zhuǎn)發(fā)請求前后執(zhí)行一些附加的動作。

      ConcreteDecoratorA和ConcreteDecoratorB是具體的裝飾,可以使用它們來裝飾具體的Component。

      Java IO包中的Decorator模式

      JDK提供的java.io包中使用了Decorator模式來實(shí)現(xiàn)對各種輸入輸出流的封裝。以下將以java.io.OutputStream及其子類為例,討論一下Decorator模式在IO中的使用。

      首先來看一段用來創(chuàng)建IO流的代碼:


      以下是代碼片段:
    try {
     OutputStream out = new DataOutputStream(new FileOutputStream("test.txt"));
    } catch (FileNotFoundException e) {
     e.printStackTrace();
    }

      這段代碼對于使用過JAVA輸入輸出流的人來說再熟悉不過了,我們使用DataOutputStream封裝了一個(gè)FileOutputStream。這是一個(gè)典型的Decorator模式的使用,F(xiàn)ileOutputStream相當(dāng)于Component,DataOutputStream就是一個(gè)Decorator。將代碼改成如下,將會更容易理解:


      以下是代碼片段:
    try {
     OutputStream out = new FileOutputStream("test.txt");
     out = new DataOutputStream(out);
    } catch(FileNotFoundException e) {
     e.printStatckTrace();
    }

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


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

      以下是代碼片段:
    public abstract class OutputStream implements Closeable, Flushable {
    public abstract void write(int b) throws IOException;
    ...
    }

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

      ByteArrayOutputStream,F(xiàn)ileOutputStream 和 PipedOutputStream 三個(gè)類都直接從OutputStream繼承,以ByteArrayOutputStream為例:

      以下是代碼片段:
    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;
    }
    ...
    }

      它實(shí)現(xiàn)了OutputStream中的write(int b)方法,因此我們可以用來創(chuàng)建輸出流的對象,并完成特定格式的輸出。它相當(dāng)于Decorator模式中的ConcreteComponent類。

      接著來看一下FilterOutputStream,代碼如下:

    以下是代碼片段:
    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繼承。但是,它的構(gòu)造函數(shù)很特別,需要傳遞一個(gè)OutputStream的引用給它,并且它將保存對此對象的引用。而如果沒有具體的OutputStream對象存在,我們將無法創(chuàng)建FilterOutputStream。由于out既可以是指向FilterOutputStream類型的引用,也可以是指向ByteArrayOutputStream等具體輸出流類的引用,因此使用多層嵌套的方式,我們可以為ByteArrayOutputStream添加多種裝飾。這個(gè)FilterOutputStream類相當(dāng)于Decorator模式中的Decorator類,它的write(int b)方法只是簡單的調(diào)用了傳入的流的write(int b)方法,而沒有做更多的處理,因此它本質(zhì)上沒有對流進(jìn)行裝飾,所以繼承它的子類必須覆蓋此方法,以達(dá)到裝飾的目的。

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

      以下是代碼片段:
    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;
    }
    ...
    }

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

      下面,將使用Decorator模式,為IO寫一個(gè)新的輸出流。

      自己寫一個(gè)新的輸出流

      了解了OutputStream及其子類的結(jié)構(gòu)原理后,我們可以寫一個(gè)新的輸出流,來添加新的功能。這部分中將給出一個(gè)新的輸出流的例子,它將過濾待輸出語句中的空格符號。比如需要輸出"java io OutputStream",則過濾后的輸出為"javaioOutputStream"。以下為SkipSpaceOutputStream類的代碼:

      以下是代碼片段:
    import java.io.FilterOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    /**
    * A new output stream, which will check the space character
    * and won’t write it to the output stream.
    * @author Magic
    *
    */
    public class SkipSpaceOutputStream extends FilterOutputStream {
     public SkipSpaceOutputStream(OutputStream out) {
      super(out);
     }
     /**
     * Rewrite the method in the parent class, and
     * skip the space character.
     */
     public void write(int b) throws IOException{
      if(b!=’ ’){
       super.write(b);
      }
     }
    }

      它從FilterOutputStream繼承,并且重寫了它的write(int b)方法。在write(int b)方法中首先對輸入字符進(jìn)行了檢查,如果不是空格,則輸出。

      以下是一個(gè)測試程序:

      以下是代碼片段:
    import java.io.BufferedInputStream;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    /**
    * Test the SkipSpaceOutputStream.
    * @author Magic
    *
    */
    public class Test {
     public static void main(String[] args){
      byte[] buffer = new byte[1024];

      /**
      * Create input stream from the standard input.
      */
      InputStream in = new BufferedInputStream(new DataInputStream(System.in));

      /**
      * write to the standard output.
      */
      OutputStream out = new SkipSpaceOutputStream(new DataOutputStream(System.out));

      try {
       System.out.println("Please input your words: ");
       int n = in.read(buffer,0,buffer.length);
       for(int i=0;i〈n;i++){
        out.write(buffer[i]);
       }
      } catch (IOException e) {
       e.printStackTrace();
      }
     }
    }

      執(zhí)行以上測試程序,將要求用戶在console窗口中輸入信息,程序?qū)⑦^濾掉信息中的空格,并將最后的結(jié)果輸出到console窗口。比如:

      以下是引用片段:
    Please input your words:
    a b c d e f
    abcdef

      總 結(jié)

      在java.io包中,不僅OutputStream用到了Decorator設(shè)計(jì)模式,InputStream,Reader,Writer等都用到了此模式。而作為一個(gè)靈活的,可擴(kuò)展的類庫,JDK中使用了大量的設(shè)計(jì)模式,比如在Swing包中的MVC模式,RMI中的Proxy模式等等。對于JDK中模式的研究不僅能加深對于模式的理解,而且還有利于更透徹的了解類庫的結(jié)構(gòu)和組成。

    posted on 2006-03-16 22:59 Web 2.0 技術(shù)資源 閱讀(279) 評論(0)  編輯  收藏 所屬分類: 設(shè)計(jì)模式
    主站蜘蛛池模板: 亚洲色成人WWW永久在线观看| 五月亭亭免费高清在线| 中文字幕亚洲综合小综合在线| 国产亚洲自拍一区| 免费无码又爽又刺激高潮| 久久国产乱子伦免费精品| 一个人看的www在线免费视频 | 亚洲人成色在线观看| 91亚洲精品第一综合不卡播放| 国产亚洲成人在线播放va| 国产成人在线观看免费网站| 曰批全过程免费视频在线观看| 99视频在线免费| 国产在线一区二区综合免费视频| eeuss影院www天堂免费| 免费人人潮人人爽一区二区| 久久久久久亚洲av无码蜜芽| 亚洲国产日韩综合久久精品| 亚洲免费闲人蜜桃| 精品无码一区二区三区亚洲桃色| 久久91亚洲精品中文字幕| 亚洲色自偷自拍另类小说| 国产精品亚洲美女久久久| 亚洲乱码日产精品a级毛片久久| 凹凸精品视频分类国产品免费| 最好免费观看韩国+日本| 在线观看成人免费视频| 最新免费jlzzjlzz在线播放| 永久免费毛片在线播放| 毛片免费在线播放| 99久久免费精品国产72精品九九| 国产无人区码卡二卡三卡免费 | 亚洲jizzjizz在线播放久| 亚洲视频在线不卡| 亚洲成在人线中文字幕| 亚洲妓女综合网99| 亚洲一线产区二线产区精华| 亚洲看片无码在线视频| 亚洲字幕AV一区二区三区四区| 亚洲欧美乱色情图片| 国产精品亚洲а∨无码播放不卡 |