使用装饰器设计模式时的问题

eva*_*n w 8 c# design-patterns decorator

我们目前正在使用装饰器设计模式来执行一些缓存.所以我们有一堆看起来像这样的类:

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"];
}
Run Code Online (Sandbox Code Playgroud)

因此,如果客户端想要使用缓存,他们将创建一个新的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;
  }
}
Run Code Online (Sandbox Code Playgroud)

问题是,从内AnotherOperation调用运行()方法()方法时,装饰实现将永远不会被调用,因为很明显的装饰是不是在ConcreteComponentA的继承层次.

那么我们在某处做出了糟糕的设计决定,还是仅仅是我们必须接受的装饰设计模式的限制?

请注意,在我的实际示例中,ConcreteComponentA是我们无法控制的第三方系统的包装器.我们已经开发了IComponent和一堆POCO,我们与之合作来抽象出第三方系统.在这种情况下,我们必须对他们的系统进行两次调用才能获得所需的数据,这只是我们进行这两次调用的地方.

mik*_*nne 4

您可以创建 AnotherOperation 的重载,它将 IComponent 用作参数。

public ConcreteComponentA : IComponent
{
  public object Operation()
  {
    return new object();
  }
  public object AnotherOperation()
  {
    return AnotherOperation(this);
  }
  public object AnotherOperation(IComponent comp)
  {
    object a = comp.Operation();
    // Do some other work
    return a;
  }
}

public ConcreteDecoratorA : IComponent
{
  protected IComponent component;
  public object Operation()
  {
    if(!this.cache.Contains("key")
    {
      this.cache["key"] = this.component.Operation();
    }
    return this.cache["key"];
  }
  public object AnotherOperation()
  {
    return this.component.AnotherOperation(this);
  }
}
Run Code Online (Sandbox Code Playgroud)