我只是在阅读责任链模式,我无法想象一个我更喜欢使用它而不是使用decorator的场景。
你怎么看?CoR 有利基用途吗?
您可以在任何时候打破链条这一事实将责任链模式与装饰者模式区分开来。装饰器可以被认为是一次执行,而不与其他装饰器进行任何交互。链中的链接可以被认为是一次执行一个,因为它们每个都依赖于前一个链接。
当您可以将程序概念化为由链接组成的链时,请使用责任链模式,其中每个链接都可以处理请求或将请求传递到链上。
当我使用 Win32 API 时,有时我需要使用它提供的挂钩功能。挂钩 Windows 消息大致遵循责任链模式。当您挂钩诸如 WM_MOUSEMOVE 之类的消息时,将调用您的回调函数。将回调函数视为链中的最后一个环节。链中的每个环节都可以决定是丢弃 WM_MOUSEMOVE 消息还是将其沿链向上传递到下一个环节。
如果在该示例中使用了装饰器模式,您将收到 WM_MOUSEMOVE 消息的通知,但您将无法阻止其他挂钩也处理它。
另一个使用命令链模式的地方是游戏引擎。同样,您可以挂钩引擎函数、事件和其他内容。对于游戏引擎,您不想简单地添加功能。您想要添加功能并阻止游戏引擎执行其默认操作。
链
通过让多个对象有机会处理请求,避免将请求的发送者与其接收者耦合。链接接收对象并沿链传递请求,直到对象处理它。
对比
装饰者
动态地将附加职责附加到对象。装饰器为扩展功能提供了一种灵活的替代子类的方法。
我会说它围绕事情发生的顺序。如果将它们链接起来,将沿链调用。使用装饰器时,您不能保证此订单,只能附加额外的责任。
我会说责任链是Decorator的一种特殊形式。
当您想向对象添加功能时使用装饰器。
当许多参与者之一可能对一个对象采取行动时,使用 COR。
根据类型调用特定的装饰器以执行操作;而COR沿着定义的链传递对象,直到其中一个参与者决定动作完成。
当有多个级别的升级到不同的处理程序时,可能会使用 COR - 例如,客户对公司的价值决定呼叫是否转到特定级别的支持的呼叫中心。
好吧,我可以想到两种情况:
现在想不出更多了,很想听到更多关于这个话题的信息。
我同意从结构的角度来看,这两种模式非常相似。我的想法是关于最终行为:
在处理请求的 CoR 元素的经典解释中,链中断了。
如果装饰器中的任何元素破坏了链条,那么这将是装饰器的错误实现,因为行为的基本部分将丢失。装饰器的想法是在基本行为保持不变时透明地添加新行为。
装饰者
装饰器模式允许将行为动态添加到单个对象。
它为扩展功能提供了一种灵活的替代子类的方法。即使它使用继承,它也继承自最低公分母 ( LCD ) 接口。
装饰器的 UML 图
结果:
有用的链接:
来自维基百科的Decorator_pattern
来自 sourcemaking 的装饰师
责任链:
责任链模式是一种由一个命令对象源和一系列处理对象组成的设计模式。每个处理对象都包含定义它可以处理的命令对象类型的逻辑;其余的被传递给链中的下一个处理对象
UML 图
这种模式在以下情况下更有效:
有用的链接:
来自维基百科的责任链模式
oodesign的责任链模式
来自sourcemaking的chain_of_responsibility
现实世界的例子:在公司中,指定的角色对处理采购请求有特定的限制。如果具有指定角色的人没有足够的权力批准采购法案,他会将命令/请求转发给拥有更大权力的继任者。该链将一直持续到命令被处理为止。
在阅读了四人帮的定义之后,我不相信有真正的区别。(为方便起见包括在内)
维基百科稍微充实了它们,但其中一些有点武断。
前两个属性并不能真正区分模式。后两个可以,但是通常实现装饰器和 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 中添加一行,如果您只想免除自己的责任,以防其他人搞砸了您的设计——但为什么要让它碰运气呢?)
我认为应用这两种模式的情况是不同的。顺便说一下,对于装饰器模式,装饰器应该知道它包装的组件。而对于 CoR 来说,不同的拦截器可能对彼此一无所知。