装饰模式使用组合而不是继承
-
06-07-2019 - |
题
我之前对装饰器模式的理解是你使用 WindowDecorator
继承 Window
,然后在重写的方法中,在调用 Window <之前做一些额外的工作/ code>执行上述方法。类似于以下内容:
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
接口;这就是允许你继续使用多态的原因。
其他提示
装饰器模式的要点是以对调用者透明的方式增强具有某些功能的对象(例如,向流添加缓冲)。为了最有效地使用它,您希望能够在不重构代码的情况下交换已修饰的实现,这基本上意味着您需要维护继承层次结构。
你真正关心的是什么,即“这对装饰的硬编码”是什么?实际意思?你想要解决什么样的问题?装修可能不是一个正确的方法......
你只需让你的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
哦经验丰富的人,请解释断开连接。
不隶属于 StackOverflow