0

我之前对装饰器模式的理解是,你继承Windowwith ,然后在被覆盖的方法中,在调用' 实现上述方法WindowDecorator之前做一些额外的工作。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();
    }
}

然而,这本质上是对装饰进行硬编码,那么如何将其重构为使用组合而不是继承呢?

4

4 回答 4

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界面;这就是允许您继续使用多态性的原因。

于 2009-05-06T11:32:41.810 回答
1

装饰器模式的重点是以对调用者透明的方式增强具有某些功能的对象(例如,向流中添加缓冲)。为了最有效地使用它,您希望能够在不重构代码的情况下交换修饰的实现,这基本上意味着您需要维护继承层次结构。

您真正关心的是什么,即“这对装饰进行硬编码”的真正含义是什么?你设想想要解决什么样的问题?可能装饰不是很正确的方法......

于 2009-05-06T11:21:28.513 回答
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();    
  }
}
于 2009-05-06T11:32:52.900 回答
0

我对装饰器模式的理解是,它旨在允许对象能力的运行时增强。在维基百科的解释中,他们专注于为此目的的组件堆栈。

我根本不会说 C#,所以这(显然)是 php-ish。似乎正确的想法是:

class image{

     function open(){ ... }

} //end of class

class decoratedImage extends image{

     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);

          }

     }

} //end of class

哦,有经验的,请解释断开连接。

于 2010-02-04T16:26:17.967 回答