2009-05-06 83 views
0

我之前對裝飾器模式的理解是,您繼承了WindowWindowDecorator,然後在重寫的方法中,在調用Window的所述方法的實現之前做一些額外的工作。以下類似:使用組合而不是繼承的裝飾器模式

public class Window 
{ 
    public virtual void Open() 
    { 
     // Open the window 
    } 
} 

public class LockableWindow : Window // Decorator 
{ 
    public virtual void Open() 
    { 
     // Unlock the window 
     base.Open(); 
    } 
} 

然而,這本質上的硬編碼裝修,所以怎麼會變成這樣被重構用的組合物,而不是繼承?

回答

7

對不起,我的C#有一點(好,非常)生鏽,所以可能有一些語法錯誤,但基本的想法是正確的。

public interface IWindow 
{ 
    void Open(); 
} 

public class Window : IWindow 
{ 
    public virtual void Open() 
    { 
     // Open the window 
    } 
} 

public class LockableWindow : IWindow 
{ 
    private IWindow _wrappedWindow; 

    public LockableWindow(IWindow wrappedWindow) 
    { 
     _wrappedWindow = wrappedWindow; 
    } 

    public virtual void Open() 
    { 
     // TODO Unlock window if necessary 
     _wrappedWindow.open(); 
    } 
} 

要注意的關鍵是新的IWindow接口;這就是允許你繼續使用多態的原因。

+0

不是生鏽的,雖然虛擬沒有必要實現接口方法 – 2009-05-06 11:37:35

+0

謝謝。實際上,我從沒有寫過.Net 1.0。只是這個問題不需要任何新的語言功能。 – 2009-05-06 11:39:21

1

Decorator模式的要點是以一種對調用者透明的方式增強具有某些功能的對象(例如,添加緩衝到流)。爲了最有效地使用它,您希望能夠在不重構代碼的情況下交換裝飾的實現,這基本上意味着您需要維護繼承層次結構。

你的實際擔憂是什麼,即「這是否對裝飾進行硬編碼」是什麼意思?你想要解決什麼樣的問題?這可能是裝飾不是很正確的做法...

0

你只需要讓你的LockableWindow定義一個構造函數,該構造函數接受一個類型爲Window的實例,它將進行修飾。你也可以通過屬性來做到這一點。

public class Window 
{  
    public virtual void Open()  
    {   
    // Open the window  
    } 
} 

public class LockableWindow // Decorator 
{  
    private Window window; 

    public LockableWindow(Window w) 
    { 
    window = w; 
    }  

    public virtual void Open()  
    {   
    // Unlock the window   
    window.Open();  
    } 
} 
0

我對裝飾模式的理解是,它旨在允許運行時增強對象的功能。在維基百科的解釋中,他們專注於爲此目的的組件堆棧。

我根本不會說C#,所以這(顯然)是php-ish。看來,正確的想法是:

一流形象{

function open(){ ... } 

} //類的結束

類decoratedImage擴展圖像{

private goodies=array(); //the alleged 'component stack' 

function addGoodie($item){ 
     $this->goodies[]=$item; 
} 

function open()}{ 

     parent::open(); 
     foreach ($this->goodies as $componentClassName){ 

      $component=new $componentClassName(); 
      $component->apply($this); 

     } 

} 

} //結束

哦有經驗的人,請解釋斷開連接。