装饰器模式和委托模式的区别
Posted
技术标签:
【中文标题】装饰器模式和委托模式的区别【英文标题】:Difference between Decorator pattern and Delegation pattern 【发布时间】:2012-11-03 13:58:02 【问题描述】:装饰者模式和委托模式(如果有的话)有什么区别?我不想只了解实现细节,还想了解用例差异以及如何使用它们的主观观点。
Decorator pattern Delegation pattern编辑:您能否指出使用这些模式(尤其是委托,因为 Java IO 类中使用了装饰)的源代码(在 OS 项目中)。我正在寻找一些真正的用法,而不仅仅是虚拟示例。也许这些模式是相同的,只是标题不同。随意写下这个意见。
【问题讨论】:
【参考方案1】:我认为“委托模式”将无法非常清楚地通过什么是或不是模式的试金石。例如,人们仍然总是说“我知道工厂模式”。没有工厂模式。这是一个成语(参见 James Coplien 的 Advanced C++)。该页面也很弱;我不认为简单的委托是责任倒置。
当被装饰的代码必须被扩充时使用装饰器。装饰器将自己包裹在被装饰者周围并仍然调用它的方法,它只是在之前或之后做一些事情。这就是你看到人们在 Aspects 出现时经常谈论 Decorator 的原因之一:它是一种依赖于中介的模式,而不是与其队列的合作。 (这也是为什么在很多情况下,例如当你没有源时,你必须使用装饰器。)
当您想要获取正在工作的东西并让它做其他事情但根本不改变界面时,装饰器的效果最好。想象一下,您有一个 Repository 类,它提供了一个接口,其中包含 CRUD 方法。现在您要添加缓存。您可以创建一个 CachedRepository 来装饰 Repository 并在读取时查找缓存,如果它不存在,那么它将调用常规存储库方法,否则,它可以只返回缓存的副本。 Repository 类中没有更改任何代码,并且该类的用户对缓存一无所知。
【讨论】:
您好,感谢您的回答。正如您在此处描述的那样,我想我非常了解装饰器。我同意你的看法。但是您对委托的描述不太清楚。你能给我指出一些关于装饰器的更好的文章吗?我试过了,有很多页面似乎人们调用委托和显示装饰,反之亦然。我对此感到很困惑。 +1 表示“委托模式将无法非常清楚地通过什么是或不是模式的试金石”。我没想到。 对我来说,正如我所说,委托不是一种模式。这只是说一件事会雇用另一件事来完成某事的一种方式。这有责任含义,并且有机会通过这些接口使事情变得更加抽象。 Coplien 将委托描述为一个成语。我什至不确定我会走那么远。我会说它基本上只是一些谨慎分工的一个插入点。如果你想阅读关于这个想法的精彩讨论,没有比 Coplien 在 Advanced C++ 中的更好的了。他将其称为信封/信函。 @Rob:你不认为这取决于模式/习语在特定语言中的使用方式。例如:在 Objective-C 中,委托模式经常被用作设计本身,而不是作为“获取正在工作的东西并让它做其他事情”的一种方式。 你误解了我的意思。我是说委托模式不是真正的模式,它肯定不是装饰器。我是说委托模式不是装饰器。【参考方案2】:装饰器使用委托,但以一种非常具体的方式。
委托(或组合)不像是一种通过协调使用其他几个对象来构建复杂行为的一般方式那样的模式。它通常以固定或静态的方式使用。 “设置或静态”我的意思是这样的:
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 的确切类型。
装饰器是一种在运行时使用委托向逻辑实体添加行为的动态方式。在 Decorator 中,所有实体共享一个公共接口,并使用委托来连接它们的工作。
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 不知道它包装的项目的确切类型,并与其共享一个公共接口。
【讨论】:
您好,感谢您的回答。在我在这里发布的 wiki 页面中,是一个复杂委托的示例,其中作者共享委托的公共接口。我从客户端寻找这两种方法(不仅仅是实现)的使用差异。也许(正如我在互联网上的许多地方发现的那样)它是相同的,只是标题不同。 装饰器是委托的子集,但定义非常明确。装饰器用于通过一次添加一个特征来构造一个复杂的对象。使用的机制是委托。所以从这个意义上说,是的,它们是同一回事。但是一个——授权——比另一个更广泛。在我看来,它们不是一回事。您不妨声称所有模式“实际上只是多态性和组合”。是的,它们是使用这些机制构建的,但它们不仅仅是它们各部分的总和。以上是关于装饰器模式和委托模式的区别的主要内容,如果未能解决你的问题,请参考以下文章