设计模式:责任链模式 vs 装饰器模式

21

责任链模式和装饰器模式有何不同?


2
类似的讨论可以在这里找到: https://dev59.com/DXRB5IYBdhLWcg3wAjXR - hoymkot
3个回答

31

我通常认为装饰器模式是对某个东西进行“添加”,而责任链模式更像是处理某个东西。

除了装饰器模式和责任链模式之间有些不同(就像是苹果和橙子),最大的区别在于,责任链模式可以在任何时候中断链。

将装饰器视为层次单元,每个层次始终进行前/后处理。责任链更像是一个链接列表,通常只有一个单元处理整个过程。

责任链模式允许多个单元处理事件,但也给它们终止链的机会。


你能给我举个例子,在什么情况下使用责任链模式或装饰器模式吗? - Mind Dead
@Mind:就像Nix所说的,这是两码事。请写下您要做什么,我们可以从那里开始帮助您。 - Marcus
我很困惑,你为什么要在第一时间比较这些看似非常不同的范式呢? - Lost Crotchet
@Marcus 假设你有一个记录函数。这里你想要装饰这个函数,因为你想要执行记录,无论成功或失败。反之,假设你想通过某种建造者创建一个对象。建造者函数可以通过链式设置,以便如果某些东西损坏,整个对象的构建可能会失败。而且很有可能你不希望最终回到原始状态。也就是说,链式模式允许中断,而装饰器则不允许。PS:(我知道我晚了十年,但我可能还是加上一些例子)。 - The 0bserver
通过调用基类的装饰器,您可以完美地在某个装饰器实例中终止执行,因此在这方面它与命令链并没有区别。 - Nickolodeon

16

情景:

想象一下一个服务请求(通常是要求管理员访问您的笔记本电脑),需要经过您的经理、总监和副总裁的批准。在这种情况下,装饰者模式会像每个级别都有他们的评论一样运作,最终您将得到一个输出。因此,经理会说“已批准并转发”,同样的,总监会说“好的,已批准并转发”,最后副总裁会说“已批准”。而您的最终输出将是这3个评论的组合。

注意:无论您的请求是否被批准或拒绝,该链都不会中断。

在职责链模式中,每个阶段的个人都有权批准或拒绝。如果在任何级别上请求被拒绝,则您的请求不会继续到下一级,而是以结果终止。希望这可以帮到你 :)


1
没有人禁止某个装饰器不再继续处理。 例如,你可以在HRDecorator.ProcessApproval(...)中编写{ if (iApprove) { nextDecorator.ProcessApproval(...) } - Nickolodeon

0
在我看来,每个责任链处理程序都决定是否处理请求或将其传递下去。通常,链中只有一个处理程序处理请求。而使用装饰器模式时,链中的所有装饰器都会对行为进行修改。
举个例子:假设你有一个咖啡类,其中有一个计算成本的函数和一个获取成分的函数。牛奶装饰器可以增加成本和成分。糖装饰器、奶油装饰器等等。装饰器包装整个类。
现在假设咖啡类改用责任链模式来计算成本和获取成分。它通过处理程序链来委托这些责任。会有一个基本处理程序咖啡成本,一个牛奶成本处理程序,一个糖成本处理程序,一个奶油成本处理程序。这里有一个棘手的部分,它还需要一个牛奶成分处理程序,一个糖成分处理程序,一个奶油成分处理程序。每个功能都有一个链。
我认为这就是装饰器模式,只是实现方式不同。如果我们将牛奶成本处理程序和牛奶成分处理程序合并,基本上就回到了装饰器模式。责任链模式应该只有一个处理程序负责整个链,而不是整个链都负责。牛奶并不确定成本,牛奶+糖+奶油才确定成本,显然这个概念也适用于成分。
PS. 请记住,装饰器是一种结构模式,而责任链是一种行为模式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接