我已经阅读了一些关于装饰器模式主题的教程,类似于this一个。基本的例子是本教程中的蛋糕,或其他教程中的披萨,装饰者通常会传递值并在途中修改它们(因为每个PizzaDecorator都会在价格上添加一小部分,从而返回价格披萨+所有装饰者)。现在,这当然是一个很好的例子,但我在应用这个问题时遇到了一些麻烦 假设我有一个接受输入的基类,根据该基类修改其状态。其中一些状态修改会导致引发事件,该事件传递可以视为输出的值。现在假设我想单独添加以下功能作为装饰器:
单独来说,它们并不是一个问题。类的基本功能(即TakeInput(byte input)
和event Handler OutputAvailable
)驻留在基类和装饰器可以继承的接口中(我真的需要额外的抽象层,如给定的示例中所示) ,即Decorator类的一个单独的接口,它继承自基接口?)。现在,如果我在装饰器中实现输入缓存,我该如何以这种方式添加它,下一个装饰器不会再次隐藏它?如果我添加一个列表来简单地存储输入并通过属性使其可用,那么如果我决定我也希望输出缓冲,则该属性将被隐藏。我可以保持对两个装饰器的引用 - 但是这会相当混乱,或者我认为,因为我将需要相当多的装饰器。如果我是从Decorator派生出来的,那么我最初希望通过应用这种模式避免的继承混乱就不会消失。我该如何解决这个问题?
根据要求,一段代码说明了我的问题。 (或者我希望,无论如何)
public interface ISampleClass
{
event OutputHandler OutputAvailable;
void TakeInput(byte input);
}
public class BaseSampleClass : ISampleClass
{
public event OutputHandler OutputAvailable;
void TakeInput(byte input)
{ // To keep things simple:
this.OutputAvailable(input);
}
}
public class SampleClassInputCacheDecorator : ISampleClass
{
private ISampleClass decoratedClass;
private List<byte> inputCache;
public event OutputHandler OutputAvailable;
public SampleClassInputCacheDecorator(ISampleClass decoratedClass)
{
this.decoratedClass = decoratedClass;
this.decoratedClass.OutputAvailable += (output) => {
this.OutputAvailable(output);
};
}
public List<byte> InputHistory { get { return this.inputCache; } }
public void TakeInput(byte input)
{
this.decoratedClass.TakeInput(input);
}
}
public class SampleClassCharInputAdapterDecorator : ISampleClass
{
private ISampleClass decoratedClass;
public SampleClassCharInputAdapterDecorator(ISampleClass decoratedClass)
{
this.decoratedClass = decoratedClass;
this.decoratedClass.OutputAvailable += (output) => {
this.OutputAvailable(output);
};
}
public void TakeInput(byte input)
{
this.decoratedClass.TakeInput(input);
}
public void TakeInput(char input)
{
switch (input)
{
case 'a':
this.TakeInput(27);
break;
case 'b':
// You get the idea...
}
}
}
// Now, I want to use the base class and get the benefit of both decorators:
ISampleClass smpl = new BaseSampleClass();
smpl = new SampleClassInputCacheDecorator(smpl);
smpl = new SampleClassCharInputAdapterDecorator(smpl);
// Dang, the input gets cached, but I can't access the InputHistory property.
答案 0 :(得分:0)
Decorator是关于改变合同行为。装饰器添加了全新的行为,与第一个行为无关,而不是合同(接口)的一部分。
事实上SampleClassInputCacheDecorator
不是装饰者 - 从ISampleClass
的角度来看,它的行为完全不相关,因为它们根本不会影响TakeInput
和OutputAvailable
。它只取决于ISampleClass
链,但不“装饰”它。 Proxy pattern似乎更合适。