第11章 結構型模式—裝飾模式

來源:互聯網
上載者:User

標籤:

1. 裝飾模式(Decorator Pattern)的定義

(1)動態地給一個對象添加一些額外的職責。就增加功能來說,裝飾模式比產生子類更為靈活。

  ①裝飾模式是為對象而不是類)添加功能的。

  ②用組合方式,而不是繼承方式為對象添加功能。

(2)裝飾模式的結構和說明

 

  ①Component:組件對象的介面,可以給這些對象動態地添加職責。

  ②ConcreteComponent:具體的組件對象,實現組件對象介面,通常就是被裝飾器裝飾的原始對象,也就是可以給這個對象添加職責。

  ③Decorator:所有裝飾器的抽象父類,需要定義一個與組件介面一致的介面,並持有一個Component對象的指標,其實就是持有一個被裝飾的對象。之所以從Decorator繼承而來,除了與被裝飾對象介面相同,還是有個原因是Decorator本身也可以被進一步的裝飾,形成多層的裝飾。注意,裝飾後仍然是一個Component對象,而且其功能更為複雜。

  ④ConcreteDecorator:實際的裝飾器對象,實現具體要向被裝飾對象添加的功能。

(3)思考裝飾模式

  ①裝飾模式的本質動態組合。動態是手段,組合才是目的。通過對象組合(而不是繼承)來實現為被裝飾對象透明的增加功能,而且也可以控制功能的訪問。

  ②裝飾模式的動機:由於繼承為類型引入的靜態特質,使得通過繼承擴充方式缺乏靈活性,並且隨著子類的增多,會導致子類的膨脹。而裝飾模式可以根據需要來動態地使“對象功能擴充”,避免子類膨脹問題

  ③裝飾器:不僅僅可以給被裝飾對象增加功能,還可以根據需要選擇是否調用被裝飾對象的功能。如果不調用,那就變成完全重新實現,相當於動態修改了被裝飾對象的功能。同時裝飾器一定要實現和組件類一致的介面,保證它們是同一個類型,並具有同一個外觀,這樣組合完成的裝飾才能夠遞迴調用下去

2. 裝飾模式的優缺點

(1)優點

  ①比繼承更靈活:繼承是靜態,而裝飾模式把功能分離到每個裝飾器,然後通過組合方式,在運行時動態地組合功能。

  ②更容易複用功能:一般一個裝飾器只實現一個功能,使實現裝飾器變得簡單,更重要的是這樣有利於裝飾器功能的複用,可以給一個對象增加多個不同裝飾器,也可以用一個裝飾器不同的對象,從而實現複用裝飾器的功能。

  ③簡化高層定義:通過組合裝飾器的方式,在進行高層定義的時候,不用把所有功能都定義出來,而是定義最基本的就可以了,在需要的時候,組合相應的裝飾器來完成所需的功能。

(2)缺點

  ①會產生很多細粒度的對象

  ②多層的裝飾是比較複雜的,應盡量減少裝飾類的資料,以便降低系統的複雜度。

3. 使用情境

(1)在不影響其他對象的情況下,以動態、透明的方式給對象添加職責。

(2)不適合使用子類來進行擴充時,可以考慮使用裝飾模式。因為裝飾模式是使用“對象組合”的方式。所謂不適合用子類擴充的方式,比如擴充功能需要的子類太多,造成子類數目呈爆炸性增長。

(3)需要為一批兄弟類進行改裝或加裝功能。可以選用裝飾模式。

【編程實驗】在顯示每個Window前追加顯示某個logo的功能。

//結構型模式:裝飾模式//情境:在顯示每個Window前追加顯示某個logo的功能。#include <iostream>using namespace std;//************************抽象組件類******************class BaseWin  //Component{public:   virtual void show() = 0; //顯示};//***********************具體組件角色*******************//PrintDialogclass PrintDialog : public BaseWin  {public:       void show()    {        cout << "PrintDialog" << endl;    }   };//WinConfig:配置視窗class WinConfig : public BaseWin  {public:       void show()    {        cout << "WinConfig" << endl;    }   };//MainWin:主視窗class MainWin : public BaseWin  {public:       void show()    {        cout << "MainWin" << endl;    }   };//*****************************裝飾器類**********************class DecoratorWin : public BaseWin //繼承,如此裝飾後仍是BaseWin類{private:    BaseWin* mWin; //持有一個被裝飾對象的指標public:    DecoratorWin(BaseWin* Win){this->mWin = Win;}    void show()    {        mWin->show();    }};//具體的裝飾器class LogWin : public DecoratorWin{private:    void displayLogo() {cout << "LogoWin Showing..." << endl;}    public:    LogWin(BaseWin* win) : DecoratorWin(win){}    void show()    {        displayLogo(); //增加功能,在原視窗顯示之前,先顯示Logo視窗        DecoratorWin::show();    }    };int main(){     //用戶端調用        //顯示主視窗前先顯示Logo視窗    BaseWin* mainWin= new MainWin();    BaseWin* logo = new LogWin(mainWin);    logo->show();    //顯示列印對話方塊前先顯示Logo視窗    BaseWin* printDlg = new PrintDialog();    BaseWin* logo2 = new LogWin(printDlg);    logo2->show();         delete mainWin;    delete logo;    delete printDlg;    delete logo2;     return 0;}

4. 相關模式

(1)裝飾模式與策略模式

  ①策略模式也可以實現動態地改變對象的功能,但是策略模式只是一層選擇,也就是根據策略選擇一下具體的實作類別而己。而裝飾模式不是一層,而是遞迴調用,無數層都可以。

  ②策略模式改變的是原始對象的功能,其改變的是對象的核心。而裝飾器可以看作是一個對象的外殼,改變的是經過前一個裝飾器裝飾後的對象,可改變對象的行為。

  ③Decorator模式僅從外部改變對象,因此對象無需對它的裝飾有任何瞭解;也就是裝飾對象該對象來說是透明的。但策略模式,Component組件本身知道可能進行哪些擴充,因此它必須引用並維護相應的策略。

  ④策略的方法可能需要修改Component組件以適應新的擴充,另一方面,一個策略可以有自己特定的介面,而裝飾的介面則必須與組件介面一致。

(2)裝飾模式與模板方法模式

  兩者的功能有點相似,模板方法主要應用在演算法骨架固定的情況。如果是一個相對動態演算法,可以使用裝飾模式,因為用裝飾器組裝時,其實也相當於一個調用演算法的步驟,相當於一個動態演算法骨架。

第11章 結構型模式—裝飾模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.