【发布时间】:2010-10-04 21:59:29
【问题描述】:
我们目前正在使用装饰器设计模式来执行一些缓存。所以我们有一堆看起来像这样的类:
interface IComponent
{
object Operation();
object AnotherOperation();
}
public ConcreteComponentA : IComponent
{
public object Operation()
{
return new object();
}
public object AnotherOperation()
{
return new object();
}
}
public ConcreteDecoratorA : IComponent
{
protected IComponent component;
public object Operation()
{
if(!this.cache.Contains("key")
{
this.cache["key"] = this.component.Operation();
}
return this.cache["key"];
}
因此,如果客户端想要使用缓存,他们将创建一个新的 ConcreteDecoratorA 并将 ConcreteComponentA 传递给构造函数。我们面临的问题是,假设 AnotherOperation() 需要调用 Operation 才能完成工作。 ConcreteComponentA 现在可能看起来像这样:
public ConcreteComponentA : IComponent
{
public object Operation()
{
return new object();
}
public object AnotherOperation()
{
object a = this.Operation();
// Do some other work
return a;
}
}
问题是在AnotherOperation()方法中调用Operation()方法时,装饰器实现永远不会被调用,因为装饰器显然不在ConcreteComponentA的继承层次中。
那么我们是否在某个地方做出了糟糕的设计决定,或者这只是我们必须接受的装饰器设计模式的限制?
请注意,在我的真实示例中,ConcreteComponentA 是我们无法控制的第三方系统的包装器。我们开发了 IComponent 和一堆 POCO,我们使用它们来抽象出第三方系统。在这种情况下,我们必须对他们的系统进行两次调用才能获取所需的数据,这就是我们进行这两次调用的地方。
【问题讨论】:
-
你无法控制ConcreteComponentA或ConcreteComponentA包裹的第三方系统吗?
-
是的,ConcreteComponentA 是我们的类之一。由于政治、预算等原因,在第三方系统中进行更改是困难的,而且极不可能发生这样的事情。所以 IComponent 定义了我们想要使用的单个操作,但是由于它们的服务结构,我们需要在 ConcreteComponentA 中的这个单个操作中进行多次调用。
-
在课堂示例中,我们在用盾牌等装饰 GameCharacters 时遇到了这个问题。被装饰的对象没有“看到”它的装饰是装饰模式的一个主要缺点——其中之一。如果一个装饰器选择添加功能并且另一个装饰器包装它,隐藏第一个装饰器的功能,教科书已经指出了透明度问题。
标签: c# design-patterns decorator