1. 程式人生 > >擴充套件系統功能——裝飾模式(二)

擴充套件系統功能——裝飾模式(二)

12.2 裝飾模式概述

      裝飾模式可以在不改變一個物件本身功能的基礎上給物件增加額外的新行為,在現實生活中,這種情況也到處存在,例如一張照片,我們可以不改變照片本身,給它增加一個相框,使得它具有防潮的功能,而且使用者可以根據需要給它增加不同型別的相框,甚至可以在一個小相框的外面再套一個大相框。

      裝飾模式是一種用於替代繼承的技術,它通過一種無須定義子類的方式來給物件動態增加職責,使用物件之間的關聯關係取代類之間的繼承關係。在裝飾模式中引入了裝飾類,在裝飾類中既可以呼叫待裝飾的原有類的方法,還可以增加新的方法,以擴充原有類的功能。

      裝飾模式定義如下:

裝飾模式(Decorator Pattern)

:動態地給一個物件增加一些額外的職責,就增加物件功能來說,裝飾模式比生成子類實現更為靈活。裝飾模式是一種物件結構型模式。

      在裝飾模式中,為了讓系統具有更好的靈活性和可擴充套件性,我們通常會定義一個抽象裝飾類,而將具體的裝飾類作為它的子類,裝飾模式結構如圖12-3所示:

12-3 裝飾模式結構圖

      在裝飾模式結構圖中包含如下幾個角色:

Component(抽象構件):它是具體構件和抽象裝飾類的共同父類,聲明瞭在具體構件中實現的業務方法,它的引入可以使客戶端以一致的方式處理未被裝飾的物件以及裝飾之後的物件,實現客戶端的透明操作。

ConcreteComponent

(具體構件):它是抽象構件類的子類,用於定義具體的構件物件,實現了在抽象構件中宣告的方法,裝飾器可以給它增加額外的職責(方法)。

Decorator(抽象裝飾類):它也是抽象構件類的子類,用於給具體構件增加職責,但是具體職責在其子類中實現。它維護一個指向抽象構件物件的引用,通過該引用可以呼叫裝飾之前構件物件的方法,並通過其子類擴充套件該方法,以達到裝飾的目的。

ConcreteDecorator(具體裝飾類):它是抽象裝飾類的子類,負責向構件新增新的職責。每一個具體裝飾類都定義了一些新的行為,它可以呼叫在抽象裝飾類中定義的方法,並可以增加新的方法用以擴充物件的行為。

      由於具體構件類和裝飾類都實現了相同的抽象構件介面,因此裝飾模式以對客戶透明的方式動態地給一個物件附加上更多的責任,換言之,客戶端並不會覺得物件在裝飾前和裝飾後有什麼不同。裝飾模式可以在不需要創造更多子類的情況下,將物件的功能加以擴充套件。

      裝飾模式的核心在於抽象裝飾類的設計,其典型程式碼如下所示:

class Decorator implements Component

{

       private Component component;  //維持一個對抽象構件物件的引用

       public Decorator(Component component)  //注入一個抽象構件型別的物件

       {

              this.component=component;

       }

       public void operation()

       {

              component.operation();  //呼叫原有業務方法

       }

}

      在抽象裝飾類Decorator中定義了一個Component型別的物件component,維持一個對抽象構件物件的引用,並可以通過構造方法或Setter方法將一個Component型別的物件注入進來,同時由於Decorator類實現了抽象構件Component介面,因此需要實現在其中宣告的業務方法operation(),需要注意的是在Decorator中並未真正實現operation()方法,而只是呼叫原有component物件的operation()方法,它沒有真正實施裝飾,而是提供一個統一的介面,將具體裝飾過程交給子類完成。

      在Decorator的子類即具體裝飾類中將繼承operation()方法並根據需要進行擴充套件,典型的具體裝飾類程式碼如下:

class ConcreteDecorator extends Decorator

{

       public ConcreteDecorator(Component  component)

       {

              super(component);

       }

       public void operation()

       {

              super.operation();  //呼叫原有業務方法

              addedBehavior();  //呼叫新增業務方法

       }

     //新增業務方法

       public  void addedBehavior()

       {    

         ……

}

}

      在具體裝飾類中可以呼叫到抽象裝飾類的operation()方法,同時可以定義新的業務方法,如addedBehavior()

由於在抽象裝飾類Decorator中注入的是Component型別的物件,因此我們可以將一個具體構件物件注入其中,再通過具體裝飾類來進行裝飾;此外,我們還可以將一個已經裝飾過的Decorator子類的物件再注入其中進行多次裝飾,從而對原有功能的多次擴充套件。

思考

能否在裝飾模式中找出兩個獨立變化的維度?試比較裝飾模式和橋接模式的相同之處和不同之處?