28

装饰器模式和委托模式(如果有的话)有什么区别?我不想只知道实现细节,还想知道用例差异和如何使用它们的主观观点。

编辑:您能否指出使用这些模式(尤其是委托,因为 Java IO 类中使用了装饰)的源代码(在 OS 项目中)。我正在寻找一些真正的用法,而不仅仅是虚拟示例。也许这些模式是相同的,只是标题不同。随意写下这个意见。

4

2 回答 2

32

装饰器使用委托,但以一种非常具体的方式。

委托(或组合)不像通过协调使用其他几个对象来构建复杂行为的一般方式那样是一种模式。它通常以固定或静态的方式使用。“设置或静态”我的意思是这样的:

class Delegator {
  private final ClassA a = new ClassA();
  private final ClassB b = new ClassB();

  public void doWork() {
     a.setup();
     final ResFromA resa = a.getRes();
     b.setup();
     b.consume(resa);
  }

}

请注意,Delegator 不与 ClassA 或 ClassB 共享任何类型或接口,并且知道 a 和 b 的确切类型。

装饰器是一种在运行时使用委托向逻辑实体添加行为的动态方式。在装饰器中,所有实体共享一个公共接口,并使用委托来连接它们的工作。

public interface Item {
  public void drawAt(final int x, final int y);
}

public class CircleAround implements Item {
  private final Item wrapped;
  private final int radius;

  public CircleAround(public final Item wrapped, public final int radius) {
    this.wrapped = wrapped;
    this.radius = radius;
  }

  public void drawAt(final int x, final int y) {
    // First handle whatever we are wrapping
    wrapped.drawAt(x,y);
    // Then add our circle
    Graphics.drawCircle(x, y, radius);
  }

}

请注意,与第一个示例不同,CircleAround 不知道它包装的项目的确切类型,并与其共享一个公共接口。

于 2012-11-15T08:17:11.020 回答
9

我认为“委托模式”将无法非常清楚地通过什么是或不是模式的试金石。例如,人们仍然总是说“我知道工厂模式”。没有工厂模式。这是一个成语(参见 James Coplien 的 Advanced C++)。该页面也很弱;我不认为简单的委托是责任倒置。

当被装饰的代码必须被扩充时使用装饰器。装饰器将自己包裹在被装饰者周围并仍然调用它的方法,它只是在之前或之后做一些事情。这是你看到人们在 Aspects 出现时经常谈论 Decorator 的原因之一:它是一种依赖于中介的模式,而不是与其队列的合作。(这也是为什么在很多情况下,例如当你没有源代码时,你必须使用装饰器。)

当您想要获取正在工作的东西并让它做其他事情但根本不改变界面时,装饰器效果最好。想象一下,您有一个 Repository 类,它提供了一个接口,其中包含 CRUD 方法。现在您要添加缓存。您可以创建一个装饰存储库的 CachedRepository 并在读取时查找缓存,如果它不存在,那么它将调用常规存储库方法,否则,它可以只返回缓存的副本。Repository 类中没有更改任何代码,并且该类的用户对缓存一无所知。

于 2012-11-15T00:20:04.250 回答