Шаблон декоратора с использованием композиции вместо наследования - PullRequest
0 голосов
/ 06 мая 2009

Мое предыдущее понимание шаблона декоратора было то, что вы наследуете Window с 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 ]

7 голосов
/ 06 мая 2009

Извините, мой 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 интерфейс; это то, что позволяет вам продолжать использовать полиморфизм.

1 голос
/ 06 мая 2009

Смысл шаблона Decorator заключается в расширении объекта с помощью некоторых функций (например, добавление буферизации в поток) таким образом, чтобы он был прозрачен для вызывающей стороны. Чтобы использовать его наиболее эффективно, вы хотите иметь возможность поменять местами декорированную реализацию без рефакторинга кода, что в основном подразумевает необходимость поддерживать иерархию наследования.

Какова ваша настоящая забота, т. Е. Что на самом деле означает «этот жесткий код украшения»? Какие проблемы вы хотите решить? Может быть, что украшение не совсем правильный подход ...

0 голосов
/ 04 февраля 2010

Мое понимание шаблона декоратора состоит в том, что он предназначен для расширения возможностей объекта во время выполнения. В объяснении в Википедии они фокусируются на стеке компонентов для этой цели.

Я вообще не говорю на 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

О, опытные, объясните, пожалуйста, разрыв.

0 голосов
/ 06 мая 2009

У вас просто есть 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();    
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...