decorator模式

參考資料


• 維基百科https://en.wikipedia.org/wiki/Decorator_patternios

• 百度百科http://baike.baidu.com/link?url=9bGoGPjJBabGJZJkGlPu-X6VJeD1c3XJifqAuCf-8xjLrt-9j7tTpigToHFXGHBDbiY8LTlFXWA8_Ewa1y3h2q編程

Decorator模式簡介


       GoF:Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
       GoF
該模式能夠動態地爲一個對象附加上額外的職責。裝飾器爲擴展功能的子類化行爲提供一個靈活的替換方案。
設計模式

      WikipediaIn object-oriented programming, the decorator pattern (also known as Wrapper, an alternative naming shared with the Adapter pattern) is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern.app

      Wikipedia在面向對象編程中,裝飾器模式(一般也稱爲包裝器模式,這種叫法也被在適配器模式中使用)是一種爲一個單獨的對象靜態或動態地添加對象行爲,同時不影響同類生成的其餘對象的行爲的設計模式。裝飾器模式一般在遵循單一責任原則的設計中十分有用,這是因爲它容許功能在兩個類之間進行拆分。ide

 

      百度百科23種設計模式之一,英文叫Decorator Pattern,又叫裝飾者模式。裝飾模式是在沒必要改變原類文件和使用繼承的狀況下,動態地擴展一個對象的功能。它是經過建立一個包裝對象,也就是裝飾來包裹真實的對象函數

Decorator模式詳解


• 設計意圖

       Decorator設計模式能夠用於靜態地擴展一個特定對象的功能,或者在某些場景能夠在運行期擴展一個特定對象的功能,而不影響與該對象的同類型(同一個類)的其餘對象。Decorator模式能夠在不改變原類文件和使用繼承的狀況下,動態地擴展一個對象的功能。它是經過建立一個包裝對象,也就是裝飾來包裹真實的對象。flex

• UML類圖

        

• 結構說明

▶ 抽象構件角色 - Component

       GoF:Defines the interface for objects that can have responsibilities added to them dynamically.編碼

       爲真實對象定義能夠動態添加功能的接口。url

▶ 具體構件角色 - Concrete Component

       GoF:Defines an object to which additional responsibilities can be attached.spa

       定義一個能夠附加額外功能的對象類型。

▶ 裝飾角色 - Decorator

       GoF:Maintains a reference to a Component object and defines an interface that conforms to Component's interface.

       維護一個指向Component對象的引用,而且定義和Component一致的接口。

▶ 具體裝飾角色 - Concrete Decorator

       GoF:Adds responsibilities to the component.

       爲Component添加具體的功能。

• 模式特色

       • 裝飾對象和真實對象具備相同的接口,這樣用戶對象就能以與真實對象交互的相同方式和裝飾對象交互。

       裝飾對象包含一個真實對象的引用。

       • 裝飾對象接受來自用戶對象的請求,並把這些請求轉發給真實的對象。

       • 在同一個真實對象之上能夠堆疊多個裝飾對象,每次堆疊能夠爲重寫函數添加新的功能點。所以咱們能夠一條終於原對象的裝飾對象鏈。

      

裝飾器鏈


       在我看來,裝飾器模式迷人之處在於能夠爲一個對象造成一個裝飾器鏈,該裝飾器鏈上每個結點只負責本身「裝飾」的功能點。這種特色使得咱們能夠不斷調整一個對象的職能,能夠任意地添加和刪除所需的功能。可以這樣實現裝飾器鏈的緣由很簡單,不管是具體的Component仍是具體的Decorator,都重寫了規約接口operation;而且Decorator和Component是處於同一繼承體系之中,咱們能夠將Decorator視爲是一種特殊的Component,但實際上繼承只是爲了多態的性質,即只須要持有Component類型的一個reference,而無所謂這個reference是引用具體的Component仍是Decorator,都可以正確調用具體的operation接口。

       在實際使用中,咱們常常能夠看到1級裝飾器D1中持有實際對象引用,2級裝飾器D2中持有裝飾器D1對象引用,以此類推。

       如下面例子一的狀況,咱們能夠編碼以下:

#include <string>
#include <iostream>
using namespace std;

// Window
class Window
{
public:
    Window() {}
    virtual ~Window() {}

public:
    virtual void   Draw()           = 0;
    virtual string GetDescription() = 0;
};

// SimpleWindow
class SimpleWindow : public Window
{
public:
    SimpleWindow() {}
    virtual ~SimpleWindow() {}

public:
    virtual void Draw()
    {
        cout << "SimpleWindow::Draw()" << endl;
    }

    virtual string GetDescription()
    {
        return "Simple Window";
    }
};

// WindowDecorator
class WindowDecorator : public Window
{
protected:
    Window &m_rWindowToBeDecorated;

public:
    WindowDecorator(Window &rWindowToBeDecorated) : m_rWindowToBeDecorated(rWindowToBeDecorated) {}
    virtual ~WindowDecorator() {}

public:
    virtual void Draw()
    {
        m_rWindowToBeDecorated.Draw();
    }

    virtual string GetDescription()
    {
        return m_rWindowToBeDecorated.GetDescription();
    }
};

// VerticalScrollBarDecorator
class VerticalScrollBarDecorator : public WindowDecorator
{
public:
    VerticalScrollBarDecorator(Window &rWindowToBeDecorated) : WindowDecorator(rWindowToBeDecorated) {}
    virtual ~VerticalScrollBarDecorator() {}

public:
    virtual void Draw()
    {
        WindowDecorator::Draw();
        DrawVerticalScrollBar();
    }

    virtual string GetDescription()
    {
        return WindowDecorator::GetDescription() + ", including vertical scrollbars";
    }

private:
    void DrawVerticalScrollBar()
    {
        cout << "VerticalScrollBarDecorator::DrawVerticalScrollBar()" << endl;
    }
};

class HorizontalScrollBarDecorator : public WindowDecorator
{
public:
    HorizontalScrollBarDecorator(Window &rWindowToBeDecorated) : WindowDecorator(rWindowToBeDecorated) {}
    virtual ~HorizontalScrollBarDecorator() {}

public:
    virtual void Draw()
    {
        WindowDecorator::Draw();
        DrawHorizontalScrollBar();
    }

    virtual string GetDescription()
    {
        return WindowDecorator::GetDescription() + ", including horizontal scrollbars";
    }

private:
    void DrawHorizontalScrollBar()
    {
        cout << "HorizontalScrollBarDecorator::DrawHorizontalScrollBar()" << endl;
    }
};

int main()
{
    SimpleWindow  window;
    VerticalScrollBarDecorator  decorated1(window);
    HorizontalScrollBarDecorator decorated2(decorated1);

    decorated2.Draw();
    cout << decorated2.GetDescription() << endl;
    return 1;
}

       輸出結果爲:

      

Decorator模式舉例


• 例子一

       這個例子出自於Wikipediahttps://en.wikipedia.org/wiki/Decorator_pattern

       以一個窗口系統中的窗口爲例。爲了可以使窗口內容進行滾動顯示,用戶可能但願在窗口中添加垂直或水平方向上的滾動條控件來實現功能。假設全部窗口都由Window這個類實例來顯示,而且初始Window類並無添加滾動條的功能。一種作法能夠建立ScrollingWindow子類來提供帶滾動條的窗口,另外一種作法是建立一個ScrollingWindowDecorator裝飾器來爲已有的Window類實例來實現功能。到目前爲止,兩種解決方案都是可行的。

       假設用戶同時也但願窗口中能增長邊框顯示的功能,而且初始Window類並無支持。ScrollingWindow窗口類此時就產生了問題,由於它其實是建立了一個新的窗口類型。若是用戶但願給大多數窗口增長邊框顯示,而不是全部窗口,那麼咱們勢必須要建立相似WindowWithBorderScrollingWindowWithBorder等的窗口類。這個問題在每增長一種新的窗口特效或窗口類型時會變得更加糟糕。若是使用裝飾器的解決方案,咱們只須要簡單地在運行期建立一個新的BorderedWindowDecorator裝飾器便可,那麼咱們可使用ScrollingWindowDecoratorBorderedWindowDecorator裝飾器來裝飾已有的窗口實例。若是用戶但願一個功能能被全部窗口所使用,那麼咱們修改基類Window來實現,反之,修改基類有時是沒有可能的,或不合法的,或不方便的行爲。

      

• 例子二

       這個例子出自於GoF,與Wikipedia的例子十分相似。

       例如,假設咱們擁有一個TextView控件來在窗口中顯示文本,在默認狀況下,TextView控件是沒有滾動功能的,由於用戶並非一直都須要文本滾動功能。當須要爲TextView實例增長文本滾動功能,咱們只須要使用ScrollDecorator裝飾器來增添功能。假設咱們須要爲TextView控件加上一個粗的黑色邊框來裝飾控件,那麼咱們要作的也只是使用BorderDecorator裝飾器來實現。在這種思路下,咱們只須要簡單地在TextView對象上組合各類裝飾器,就能產生咱們所須要的結果。
      

       下面的對象關係圖顯示了怎樣在TextView對象上組合使用BorderDecoratorScrollDecorator裝飾器對象來產生一個帶邊框和滾動條的文本視圖:
      

相關文章
相關標籤/搜索