为什么我会用装饰者的责任链?

我只是阅读责任链模式,我很难想象一个场景,当我更喜欢它的使用,而不是装饰 。

你怎么看? CoR是否有利基用途?

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

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

当我使用Win32 API时,有时需要使用它提供的挂钩function。 挂钩Windows消息大致遵循责任链模式。 当你挂钩一个消息,如WM_MOUSEMOVE,你的callback函数将被调用。 将callback函数看作链中的最后一个链接。 链中的每个链接都可以决定是否丢弃WM_MOUSEMOVE消息或者将链传递给下一个链接。

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

使用命令链模式的另一个地方是在游戏引擎中。 再次,您可以挂钩引擎function,事件和其他事情。 在游戏引擎的情况下,你不想简单地添加function。 您想要添加function并阻止游戏引擎执行其默认操作。

这些模式之间的区别并不涉及何时或如何链可以被打破(假设链)或额外的行为何时执行。 他们的相关之处在于,他们都使用构成来支持inheritance,以提供更为灵活的解决scheme。

关键的区别是一个装饰器增加了新的行为,实际上拓宽了原始的界面。 它与正常的扩展可以如何添加方法相似,除了“子类”仅通过引用耦合,意味着可以使用任何“超类”。

COR模式可以修改现有的行为,类似于使用inheritance覆盖现有的方法。 您可以select调用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还会在进食之前吠叫一次,这已经改变了现有的function,因此类似于COR。 但是,意图与COR不同,即find一种能够吃食物的动物。 这里的意图是修改行为。

你可以想象一个COR被用来find一个能够把动物散步的人。 这可以像chained上面的链接列表或作为一个明确的List …或其他。

希望这是相当清楚的!

约翰

通过给予多个对象一个机会来处理请求,避免将请求的发送者耦合到它的接收者。 链接接收对象,并沿着链传递请求,直到对象处理它。

VS

装饰

将其他职责dynamic地附加到对象。 装饰器为扩展function提供了子类化的灵活替代scheme。

我会说事情将会发生的顺序。 如果你把它们连起来,就会沿着链条被调用。 有了装饰者,你不能保证这个订单,只能附加额外的责任。

我想说, 责任链装饰者的一种特殊forms。

当你想添加function到一个对象时使用装饰者。

当许多参与者中的一个可能对某个对象采取行动时,就会使用COR。

调用一个特定的装饰器根据types采取行动; 而COR则通过定义的链传递对象,直到其中一个angular色决定动作完成。

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

那么我可以想到2种情况:

  • 你没有一个核心对象,也就是说在你通过所有的图层/filter之后,你不知道该怎么做。 (类似于拦截器链这样的方面,并不关心请求结束的地方)。
  • 您需要select性地对请求进行一些预处理或后处理。 不是装饰者所做的一般增强forms。 即filter可能或可能不处理特定的请求,但添加装饰器总是增强您的对象的一些function。

现在再也想不起来了,很想在这个话题上听到更多。

装饰

  1. 装饰模式允许行为dynamic添加到单个对象。

  2. 它为扩展function提供了子分类的灵活替代scheme。 尽pipe它使用inheritance,它inheritance了最低公分母(LCD)接口。

装饰者的UML图

装饰者的UML图

后果:

  1. 装饰也可以dynamic地删除附加的function。
  2. 装饰在运行时增加了对象的function,这会使debugging系统function更难。

有用的链接:

何时使用装饰模式?

来自维基百科的Decorator_pattern

来自源头的装饰者

责任链:

责任链模式是由命令对象源和一系列处理对象组成的devise模式。 每个处理对象都包含用于定义可处理的命令对象types的逻辑; 其余的被传递给链中的下一个处理对象

UML图

在这里输入图像说明

在以下情况下,此模式更有效:

  1. 多个对象可以处理一个命令
  2. 处理程序不提前知道
  3. 处理程序应该自动确定
  4. 希望这个请求是针对一组对象而没有明确指定它的接收者
  5. 可以处理命令的对象组必须以dynamic方式指定

有用的链接:

维基百科的责任链模式

oodesign 的责任链模式

源头的责任

现实世界的例子:在一家公司里,一个指定的angular色对处理采购申请有特别的限制。 如果具有指定angular色的人没有足够的权力批准购买账单,他将把命令/请求转发给有更多权力的继任者。 这个链将继续,直到命令被处理。

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

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

如果装饰器中的任何元素打断链,那么这将是错误的装饰器的实现,因为基础部分的行为将会丢失。 当装饰者的基本行为保持不变时,装饰者的想法是透明的join新的行为。

  1. 关键字“扩展” – 静态扩展。
  2. 装饰者模式 – dynamic扩展。
  3. 责任链模式 – 只是用一组处理对象来处理一个命令对象,而这些对象并不相互了解。

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

看完“四人帮”的定义之后,我不相信这是真正的区别。 (包括为了方便)

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

维基百科把它们稍微分开了一些,但是其中有些是随意的。

  • 装饰者通常被实现为链接列表。 但是我认为这太低级了,不能被视为模式的“一部分”。
  • 如果责任链只是他们的责任,链接只处理数据; 但确定责任和数据处理都是行为的一部分。 装饰者可以轻松地做到这一点。
  • 装饰者需要您调用委托。
  • 如果不处理数据,“纯”的CoR链接只应该调用委托。

前两个属性并没有真正区分这些模式。 其次,Decorator和CoR的实现方式通常不会强制实现这些属性 – devise者只是希望没有人写一个破坏链的装饰器或一个处理数据后继续链的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中添加一行,如果你想要的是为了免除责任,以防其他人把你的devise搞砸了,但是为什么还要这样做?)