我只是阅读了Chain of Responsibility模式,当我更喜欢使用decorator时,我无法想象一个场景。
你怎么看? CoR是否有利基用途?答案 0 :(得分:64)
您可以在任何时候打破链条,将责任链模式与装饰器模式区分开来。装饰器可以被认为是一次执行而不与其他装饰器进行任何交互。链中的链接可以被认为是一次执行一个,因为它们各自依赖于前一个链接。
当您可以将您的程序概念化为由链接组成的链时,使用责任链模式,其中每个链接可以处理请求或将其传递给链。
当我以前使用Win32 API时,我有时需要使用它提供的挂钩功能。挂钩Windows消息大致遵循责任链模式。当您挂钩诸如WM_MOUSEMOVE之类的消息时,将调用您的回调函数。将回调函数视为链中的最后一个链接。链中的每个链接都可以决定是丢弃WM_MOUSEMOVE消息还是将链路传递到下一个链接。
如果在该示例中使用了Decorator模式,则会收到WM_MOUSEMOVE消息的通知,但是您也无法阻止其他挂钩处理它。
使用命令链模式的另一个地方是游戏引擎。同样,您可以挂钩引擎功能,事件和其他事物。对于游戏引擎,您不希望简单地添加功能。您希望添加功能并阻止游戏引擎执行其默认操作。
答案 1 :(得分:16)
这些模式之间的差异与链的何时或如何被破坏(假定链)或何时执行额外行为无关。它们的相关之处在于它们都使用组合来支持继承,以提供更灵活的解决方案。
关键区别在于装饰器添加了新行为,实际上扩大了原始界面。它类似于普通扩展可以添加方法的方式,除了“子类”仅通过引用耦合,这意味着可以使用任何“超类”。
COR模式可以修改现有行为,类似于使用继承覆盖现有方法。您可以选择调用super.xxx()继续“链”或自己处理消息。
所以区别是微妙的,但装饰者的一个例子应该有所帮助:
interface Animal
{
Poo eat(Food food);
}
class WalkingAnimal implements Animal
{
Animal wrapped;
WalkingAnimal(Animal wrapped)
{
this.wrapped = wrapped;
}
Position walk(Human walker)
{
};
Poo eat(Food food)
{
return wrapped.eat(food);
}
}
class BarkingAnimal implements Animal
{
Animal wrapped;
BarkingAnimal(Animal wrapped)
{
this.wrapped = wrapped;
}
Noise bark()
{
};
Poo eat(Food food)
{
bark();
return wrapped.eat();
}
}
你可以看到我们可以组成一只行走的,吠叫的动物......或者实际上增加了对任何动物吠叫的能力。要直接使用这种额外的行为,我们需要保持对BarkingAnimal装饰器的引用。
所有BarkingAnimal在吃之前都会吠叫一次,这改变了现有的功能,因此类似于COR。但意图与COR不同,即找到一个会吃掉食物的动物。这里的目的是修改行为。
你可以想象一个COR应用于寻找一个将动物带走的人。这可以实现为上面的chained
链接列表,也可以显示为明确的列表......或其他任何内容。
希望这是相当清楚的!
约翰
答案 2 :(得分:13)
<强>链强>
避免耦合请求的发件人 给予接收者超过 一个物体有机会处理 请求。链接接收对象 并沿着链传递请求 直到一个对象处理它。
VS
<强>装饰强>
将附加职责附加到 一个动态的对象。装饰 提供灵活的替代方案 子类化扩展 功能。
我会围绕事情发生的顺序说出来。如果你链接它们,将沿着链调用。对于装饰者,您无法保证此订单,只能附加额外的责任。
答案 3 :(得分:9)
我会说责任链是装饰者的一种特殊形式。
答案 4 :(得分:8)
当您想要向对象添加功能时使用Decorator。
当许多演员中的一个可能对某个对象采取行动时使用COR。
根据类型调用特定的装饰器来执行操作; COR沿着定义的链传递对象,直到其中一个角色决定动作完成。
当有多个级别的升级到不同的处理程序时,可能会使用COR - 例如,客户对公司的价值决定调用是否达到特定支持级别的呼叫中心。
答案 5 :(得分:4)
我能想到两种情况:
现在不能再想了,希望在这个话题中听到更多。
答案 6 :(得分:2)
<强> 装饰 强>
Decorator模式允许动态地将行为添加到单个对象。
它为子分类提供了灵活的替代方案,可用于扩展功能。即使它使用继承,它仍然从最低公分母(LCD)接口继承。
装饰器的UML图
<强>后果:强>
有用的链接:
When to Use the Decorator Pattern?
来自维基百科的 来自sourcemaking的责任链
责任链模式是一种由命令对象源和一系列处理对象组成的设计模式。每个处理对象都包含定义它可以处理的命令对象类型的逻辑;其余的传递给链中的下一个处理对象
UML图
这种模式在以下情况下更有效:
有用的链接:
来自维基百科的Chain-of-responsibility_pattern
来自oodesign的chain-of-responsibility-pattern
来自sourcemaking的真实世界示例:在公司中,指定角色对处理购买请求有特定限制。如果具有指定角色的人没有足够的权力来批准购买账单,他会将命令/请求转发给拥有更多权力的继任者。此链将继续,直到处理命令。
答案 7 :(得分:1)
我同意从结构角度来看,这两种模式非常相似。我的想法是关于最终的行为:
在处理请求的CoR元素的经典解释中打破链。
如果装饰器中的任何元素打破了链,那么它将是错误的装饰器的实现,因为基本部分的行为将会丢失。当基本行为保持不变时,装饰者的想法是透明地添加新行为。
答案 8 :(得分:0)
我认为应用这两种模式的情况是不同的。顺便说一句,对于装饰器模式,装饰器应该知道它包装的组件。而对于CoR来说,不同的拦截器可能彼此都不知道。
答案 9 :(得分:0)
在阅读“四人帮”定义后,我不相信存在真正的差异。 (为方便起见,包括在内)
维基百科将它们搞砸了一点,但其中一些有点武断。
前两个属性并没有真正区分模式。第二个做,但Decorator和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上添加一行,如果你想要的就是免除责任,以防其他人搞砸你的设计 - 但为什么要把它留给机会?)