【问题标题】:Decorator Pattern Using Composition Instead of Inheritance使用组合而不是继承的装饰器模式
【发布时间】:2009-05-06 11:16:12
【问题描述】:

我之前对装饰器模式的理解是,你用WindowDecorator继承Window,然后在被覆盖的方法中,在调用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();
    }
}

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

【问题讨论】:

    标签: c# design-patterns decorator composition


    【解决方案1】:

    抱歉,我的 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 接口;这就是允许您继续使用多态性的原因。

    【讨论】:

    • 没那么生疏,虽然 virtual 不是实现接口方法所必需的
    • 谢谢。实际上,自从 .Net 1.0 以来,我还没有写过任何东西。只是这个问题不需要任何新的语言特性。
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      您只需让 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();    
        }
      }
      

      【讨论】:

      • 这里的一个问题是LockableWindow 不是Window 的多态。编辑:刚刚注意到这在 OP 中是正确的。
      【解决方案4】:

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

      我根本不会说 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
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-18
        • 2015-05-27
        • 2012-09-04
        • 2012-07-24
        • 2018-04-17
        • 2015-02-17
        • 2017-09-19
        • 2011-09-05
        相关资源
        最近更新 更多