Шаблон декоратора с использованием композиции вместо наследования
-
06-07-2019 - |
Вопрос
Мое предыдущее понимание шаблона декоратора заключалось в том, что вы наследуете 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();
}
}
Однако это, по сути, жестко закодировано для декорации, так как бы это было реорганизовано для использования композиции вместо наследования?
Решение
Извините, мой 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
; это то, что позволяет вам продолжать использовать полиморфизм.
Другие советы
Смысл шаблона Decorator заключается в расширении объекта с помощью некоторых функций (например, добавление буферизации в поток) таким образом, чтобы он был прозрачен для вызывающей стороны. Чтобы использовать его наиболее эффективно, вы хотите иметь возможность менять декорированную реализацию без рефакторинга кода, что в основном подразумевает необходимость поддерживать иерархию наследования.
Какова ваша настоящая забота, т. е. что означает "это жестко кодирует украшение"? на самом деле означает? Какие проблемы вы хотите решить? Может быть, что украшение не совсем правильный подход ...
У вас просто есть 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();
}
}
Мое понимание шаблона декоратора состоит в том, что он предназначен для расширения возможностей объекта во время выполнения. В объяснении в Википедии они фокусируются на стеке компонентов для этой цели.
Я вообще не говорю на 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
О, опытные, объясните, пожалуйста, разрыв.