Java 裝飾器模式詳解


轉載請注明出處:http://blog.csdn.net/zhaoyanjun6/article/details/56488020

 

前言

在上面的幾篇文章中,着重介紹了Java 中常見的 IO 相關知識,在學習的過程中,發現 IO 包中是用了大量的裝飾器模式,為了徹底的學習 IO,今天就來揭開裝飾器模式的面紗。

為了弄明白裝飾器模式的本質,我查看了很多資料,發現有很多文章要么說的很苦澀,要么舉的例子不恰當。

其實我們可以這樣理解裝飾器模式, 就拿自己舉例子,你把自己裸體的樣子,想象成被裝飾的對象。你的鞋子,你的寸衣,你的外套,你的手表,你的帽子 等等,都是你的裝飾物,你和這些裝飾物,是裝飾和被裝飾的關系。

 

實例展示

好了,現在我們用代碼的方法去理解這樣概念。

首先,我們發現,不管是裸體的人,還是你的鞋子、帽子,都有展示的功能,我們稱之為show 方法。

我們定義一個接口,它具有展示的功能,也就是show() , 

package com.user;

/**
 * 定義接口
 * @author T
 *
 */
public interface AbstractPerson {

    //具有展示的功能
    void show() ;
}

 

現在應該定義一個裸體的自己了,Me 類

package com.user;

/**
 * 定義一個具體的人,就是被裝飾者
 * @author T
 *
 */
public class Me implements AbstractPerson {

    @Override
    public void show() {
        System.out.println( "什么都沒穿,我展示的是裸體");
    }

}

 

下面該定義,鞋子,帽子,手表等 裝飾物,等等先別急,我們應該先定義一個鞋子,帽子,手表的抽象父類 AbstractClothes 。 其實抽象的父類有一個構造函數,構造函數里面的參數是抽象的人類,這里的用法很巧妙,這也是能夠實現裝飾功能的一個必不可少的步驟。

package com.user;

/**
 * 定義抽象裝飾物
 * @author T
 *
 */
public abstract class AbstractClothes implements AbstractPerson {

    AbstractPerson abstractPerson ;

    public AbstractClothes( AbstractPerson abstractPerson ){
        this.abstractPerson = abstractPerson ;
    }

    @Override
    public void show() {
        abstractPerson.show();
    }

}

 

下面開始定義,帽子裝飾物  Hat 類, 繼承 AbstractClothes 類

package com.user;

/**
 * 帽子裝飾物
 * @author T
 *
 */
public class Hat extends AbstractClothes {

    public Hat(AbstractPerson abstractPerson) {
        super(abstractPerson);
    }
    
    @Override
    public void show() {
        super.show();
        say();
    }
    
    public void say(){
        System.out.println( "我展示一個帽子");
    }

}

 

定義鞋子裝飾類 Shoes ,   繼承 AbstractClothes 類

package com.user;

/**
 * 鞋子裝飾物
 * @author T
 *
 */
public class Shoes extends AbstractClothes {

    public Shoes(AbstractPerson abstractPerson) {
        super(abstractPerson);
    }
    
    @Override
    public void show() {
        super.show();
        say();
    }
    
    public void say(){
        System.out.println( "我展示一雙鞋子");
    }
}

 

創建測試類 Test

package com.user;

public class Test {

    public static void main(String[] args) {

        //創建被裝飾者
        Me me = new Me() ;

        //裸體的人被裝飾了帽子 ,具有了展示帽子的能力
        Hat hat = new Hat( me ) ;

        // 帶了帽子的人被裝飾了鞋子,具有了展示鞋子的本領
        Shoes shoes = new Shoes( hat ) ;

        shoes.show();
    }
}

 運行結果:

什么都沒穿,我展示的是裸體
我展示一個帽子
我展示一雙鞋子

裝飾器模式的類圖

在學習完了一個小例子之后,我們試着總結出裝飾器模式的類圖。

裝飾器模式類圖:

 

  • Component抽象構件角色:真實對象和裝飾對象有相同的接口。這樣,客戶端對象就能夠以與真實對象相同的方式同裝飾對象交互。
  • ConcreteCompoent具體構建角色(真實對象):定義一個將要接收附加責任的類。
  • Decorator裝飾角色:持有一個抽象構件的引用。裝飾對象接受所有客戶端的請求,並把這些請求轉發給真實的對象。這樣,就能在真實對象調用前后增加新的功能。
  • ConcreteDecorate具體裝飾角色:負責給構件對象增加新的功能。

 

裝模式在Java I/O庫中的應用

IO流實現細節:

  • Component抽象構件角色:io流中的InputStream,OutputStream,Reader,Writer
  • ConcreteComponent具體構件角色:io流中的FileInputStream,FileOutputStream
  • Decorate裝飾角色:持有抽象構件的引用,FilterInputStream,FilterOutputStream
  • ConcreteDecorate具體裝飾角色:負責給構件對象添加新的責任,BufferedInputStream,BufferedOutputStream等

 

優點

  •  擴展對象功能,比繼承靈活,不會導致類個數急劇增加。
  • 可以對一個對象進行多次裝飾,創造出不同行為的組合,得到功能更加強大的對象。
  • 具體構件類和具體裝飾類可以獨立變化,用戶可以根據需要自己增加新的 具體構件子類和具體裝飾子類。

 

缺點

  • 產生很多小對象。大量小的對象占據內存,一定程度上影響性能。
  • 裝飾模式易出錯,調試排查比較麻煩。
 

總結

  • 裝飾模式(Decorate)也叫包裝模式(Wrapper)
  • 裝飾模式降低系統的耦合度,可以動態的增加或刪除對象的責任,並使得需要裝飾的具體構建類和具體裝飾類可以獨立變化,以便增加新的具體構建類和具體裝飾類。

 

參考資料:

Java設計模式學習09——裝飾模式

Java與模式:裝飾(Decorator)模式

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM