73

我只是在阅读责任链模式,我无法想象一个我更喜欢使用它而不是使用decorator的场景。

你怎么看?CoR 有利基用途吗?

4

10 回答 10

73

您可以在任何时候打破链条这一事实将责任链模式与装饰者模式区分开来。装饰器可以被认为是一次执行,而不与其他装饰器进行任何交互。链中的链接可以被认为是一次执行一个,因为它们每个都依赖于前一个链接。

当您可以将程序概念化为由链接组成的链时,请使用责任链模式,其中每个链接都可以处理请求或将请求传递到链上。

当我使用 Win32 API 时,有时我需要使用它提供的挂钩功能。挂钩 Windows 消息大致遵循责任链模式。当您挂钩诸如 WM_MOUSEMOVE 之类的消息时,将调用您的回调函数。将回调函数视为链中的最后一个环节。链中的每个环节都可以决定是丢弃 WM_MOUSEMOVE 消息还是将其沿链向上传递到下一个环节。

如果在该示例中使用了装饰器模式,您将收到 WM_MOUSEMOVE 消息的通知,但您将无法阻止其他挂钩也处理它。

另一个使用命令链模式的地方是游戏引擎。同样,您可以挂钩引擎函数、事件和其他内容。对于游戏引擎,您不想简单地添加功能。您想要添加功能并阻止游戏引擎执行其默认操作。

于 2009-04-14T14:54:24.097 回答
15

通过让多个对象有机会处理请求,避免将请求的发送者与其接收者耦合。链接接收对象并沿链传递请求,直到对象处理它。

对比

装饰者

动态地将附加职责附加到对象。装饰器为扩展功能提供了一种灵活的替代子类的方法。

我会说它围绕事情发生的顺序。如果将它们链接起来,将沿链调用。使用装饰器时,您不能保证此订单,只能附加额外的责任。

于 2009-04-14T14:49:43.063 回答
14

我会说责任链是Decorator的一种特殊形式。

于 2009-04-14T14:41:05.923 回答
8

当您想向对象添加功能时使用装饰器。

当许多参与者之一可能对一个对象采取行动时,使用 COR。

根据类型调用特定的装饰器以执行操作;而COR沿着定义的链传递对象,直到其中一个参与者决定动作完成。

当有多个级别的升级到不同的处理程序时,可能会使用 COR - 例如,客户对公司的价值决定呼叫是否转到特定级别的支持的呼叫中心。

于 2009-04-14T14:50:25.450 回答
4

好吧,我可以想到两种情况:

  • 您没有核心对象,即在请求通过所有层/过滤器后,您不知道如何处理请求。(类似于拦截器链之类的方面,它并不真正关心请求在哪里结束)。
  • 您需要有选择地对请求应用一些预处理或后处理。不像装饰器那样采用一般的增强形式。即过滤器可能会或可能不会处理特定请求,但添加装饰器总是会通过某些功能增强您的对象。

现在想不出更多了,很想听到更多关于这个话题的信息。

于 2009-04-14T14:49:27.510 回答
3

我同意从结构的角度来看,这两种模式非常相似。我的想法是关于最终行为:

在处理请求的 CoR 元素的经典解释中,链中断了。

如果装饰器中的任何元素破坏了链条,那么这将是装饰器的错误实现,因为行为的基本部分将丢失。装饰器的想法是在基本行为保持不变时透明地添加新行为。

于 2010-12-11T22:42:28.043 回答
2

装饰者

  1. 装饰器模式允许将行为动态添加到单个对象。

  2. 它为扩展功能提供了一种灵活的替代子类的方法。即使它使用继承,它也继承自最低公分母 ( LCD ) 接口。

装饰器的 UML 图

装饰器的 UML 图

结果:

  1. 通过装饰,还可以动态删除添加的功能。
  2. 装饰在运行时向对象添加功能,这会使调试系统功能更加困难。

有用的链接:

何时使用装饰器模式?

来自维基百科的Decorator_pattern

来自 sourcemaking 的装饰师

责任链:

责任链模式是一种由一个命令对象源和一系列处理对象组成的设计模式。每个处理对象都包含定义它可以处理的命令对象类型的逻辑;其余的被传递给链中的下一个处理对象

UML 图

在此处输入图像描述

这种模式在以下情况下更有效:

  1. 多个对象可以处理一个命令
  2. 处理程序事先不知道
  3. 处理程序应自动确定
  4. 希望将请求发送给一组对象,而无需明确指定其接收者
  5. 必须以动态方式指定可以处理命令的对象组

有用的链接:

来自维基百科的责任链模式

oodesign的责任链模式

来自sourcemaking的chain_of_responsibility

现实世界的例子:在公司中,指定的角色对处理采购请求有特定的限制。如果具有指定角色的人没有足够的权力批准采购法案,他会将命令/请求转发给拥有更大权力的继任者。该链将一直持续到命令被处理为止。

于 2016-04-05T16:55:21.030 回答
1
  1. 关键字“扩展” - 静态扩展。
  2. 装饰器模式——动态扩展。
  3. 责任链模式 - 仅使用一组处理对象处理命令对象,并且这些对象彼此不知道。
于 2012-01-24T11:38:43.967 回答
1

在阅读了四人帮的定义之后,我不相信有真正的区别。(为方便起见包括在内)

  • 装饰器:允许动态包装对象以修改它们现有的职责和行为
  • 责任链:通过将接收对象链接在一起,为多个对象提供处理请求的机会

维基百科稍微充实了它们,但其中一些有点武断。

  • 装饰器通常实现为链表。但我认为这太低级了,不能被视为模式的“一部分”。
  • 责任链链接仅在其负责时处理数据;但确定责任和数据处理都是行为的一部分。装饰者可以很容易地做到这一点。
  • 装饰器要求您调用委托。
  • “纯” CoR 链接仅应在不处理数据的情况下调用委托。

前两个属性并不能真正区分模式。后两个可以,但是通常实现装饰器和 CoR 的方式并没有强制执行这些属性——设计者只是希望没有人编写破坏链的装饰器或在处理数据后继续链的 CoRLink。

要实际实现这些属性,您需要以下内容。

强制装饰器:

abstract class Decorated {

public Decorated delegate;

public final Object doIt(Object args) {
    Object returnVal = behavior(arg);
    if(delegate != null) returnVal = delegate.doit(returnVal);
    return returnVal;
}

protected abstract Object behavior(Object args); //base or subclass behavior
}

强制责任链:

abstract class Link {

public Link delegate;

public final Object processIt(Obect args) {
    Object returnVal = args;
    if(isMyResponsibility) returnVal = processingBehavior(returnVal);
    else returnVal = delegate.processIt(returnVal);
    return returnVal;
}

protected abstract Boolean isMyResponsibility(Object args);

protected abstract Object processingBehavior(Object args);
}

(或者,您可以在 javadoc 中添加一行,如果您只想免除自己的责任,以防其他人搞砸了您的设计——但为什么要让它碰运气呢?)

于 2014-03-18T19:09:24.007 回答
0

我认为应用这两种模式的情况是不同的。顺便说一下,对于装饰器模式,装饰器应该知道它包装的组件。而对于 CoR 来说,不同的拦截器可能对彼此一无所知。

于 2011-11-05T16:51:36.247 回答