为啥我会在装饰器上使用责任链?
Posted
技术标签:
【中文标题】为啥我会在装饰器上使用责任链?【英文标题】:Why would I ever use a Chain of Responsibility over a Decorator?为什么我会在装饰器上使用责任链? 【发布时间】:2010-10-19 08:59:24 【问题描述】:我只是在阅读Chain of Responsibility 模式,我无法想象一个我宁愿使用它而不是decorator 的场景。
你怎么看? CoR 有小众用途吗?
【问题讨论】:
请添加一种你认为是 CoR 的任务,但你用装饰器解决了它 当然,我需要完成订单,在某些情况下我需要打印账单。我的装饰器解决方案是将核心 OrderCompleter 包裹在 OrderCompletionPrintDecorator 中,它应用条件逻辑和打印。与任何链条一样有效。 为什么不能在 OrderCompleter 中只使用一个名为“Print”的方法,以便在您想要(不想要)打印时使用(或不使用)?换句话说,我想知道你是否可以完全不使用任何模式来解决这个任务?在我看来,这似乎不是一项真正需要引入抽象和复杂性的复杂任务。或者也许你所说的只是问题的过度简化版本。 @SonDo 这取决于 - 但是是的,这是一个过于简化的版本。问题是,什么东西打印出来的逻辑在哪里?如果这是一个简单的决定,它可以直接进入OrderCompleter.Complete()
,但它可能是这样的:“如果打印服务响应 ping 并且该订单或父订单尚未打印,并且下订单的客户确实不直接与我们的系统集成。”
【参考方案1】:
我会说责任链是装饰器的一种特殊形式。
【讨论】:
一行说明一切【参考方案2】:嗯,我可以想到两种情况:
您没有核心对象,即在请求通过所有层/过滤器后,您不知道如何处理该请求。 (类似于拦截器链之类的方面,它并不真正关心请求在哪里结束)。 您需要有选择地对请求应用一些预处理或后处理。不像装饰器那样采用一般的增强形式。即过滤器可能会或可能不会处理特定请求,但添加装饰器始终可以通过某些功能增强您的对象。现在想不出更多了,很想听听这个话题的更多内容。
【讨论】:
【参考方案3】:链
避免耦合请求的发送者 通过给予超过 一个对象有机会处理 要求。链接接收对象 并沿链传递请求 直到一个对象处理它。
对
装饰器
附加额外的职责 动态的对象。装饰器 提供灵活的替代方案 用于扩展的子类化 功能。
我会说它围绕事情发生的顺序。如果将它们链接起来,将沿链调用。对于装饰者,您不能保证这个订单,只能附加额外的责任。
【讨论】:
你可以按不同的顺序附加,不是吗? 如果我们从类消费者的观点来看你是绝对正确的,但是如果我们是从类设计师的观点来看,你当然可以像链条一样保证这一点可以。【参考方案4】:装饰器用于为对象添加功能。
当许多参与者之一可能对一个对象采取行动时,使用 COR。
一个特定的装饰器被调用以根据类型采取行动;而 COR 沿着定义的链传递对象,直到其中一个参与者决定动作完成。
当有多个级别的升级到不同的处理程序时,可能会使用 COR - 例如,客户对公司的价值决定呼叫是否转到特定级别的支持的呼叫中心。
【讨论】:
好的,但我的意思是,你可以用同样多甚至更少的努力来使用装饰器。那么,为什么还要涉及 CoR? 但是装饰器是一种不同的模式——使用 COR,对象从一个演员传递到另一个演员,直到有人说它完成了动作;使用装饰器,该操作将在一个特定类的实现上执行。【参考方案5】:您可以在任何时候打破链条这一事实将责任链模式与装饰者模式区分开来。装饰器可以被认为是一次执行,而不与其他装饰器进行任何交互。链中的链接可以被认为是一次执行一个,因为它们每个都依赖于前一个链接。
当您可以将程序概念化为由链接组成的链时,请使用责任链模式,其中每个链接可以处理请求或将请求传递到链上。
当我使用 Win32 API 时,有时我需要使用它提供的挂钩功能。挂钩 Windows 消息大致遵循责任链模式。当您挂钩诸如 WM_MOUSEMOVE 之类的消息时,将调用您的回调函数。将回调函数视为链中的最后一个环节。链中的每个环节都可以决定是丢弃 WM_MOUSEMOVE 消息还是将其传递到链上的下一个环节。
如果在该示例中使用了装饰器模式,您将收到 WM_MOUSEMOVE 消息的通知,但您将无法阻止其他钩子也处理它。
使用命令链模式的另一个地方是游戏引擎。同样,您可以挂钩引擎函数、事件和其他内容。对于游戏引擎,您不想简单地添加功能。您想添加功能并阻止游戏引擎执行其默认操作。
【讨论】:
IMO 在 CoR 模式中,我们可以拥有许多(或所有)处理程序(链接)对象,这些对象可以参与每个请求的处理/构建响应。 所以你是说它可以替代嵌套的 if...else 语句,除非最后没有 else 部分? @Rishi,这很容易想象,但 GoF 并未提及。在他们的 CoR 模式中,每个请求只处理一次或根本不处理。 @DiponRoy,是的,但是,CoR 模式的关键点是解耦。在 if...else 块中,调用者会看到每个分支。在 CoR 中,调用者甚至不知道链的存在。【参考方案6】:我同意从结构的角度来看,这两种模式非常相似。我的想法是关于最终行为:
在处理请求的 CoR 元素的经典解释中,会破坏链。
如果装饰器中的任何元素破坏了链,那么这将是装饰器的错误实现,因为行为的基本部分将丢失。装饰器的想法是在基本行为保持不变时透明地添加新行为。
【讨论】:
【参考方案7】:我认为应用这两种模式的情况是不同的。顺便说一句,对于装饰器模式,装饰器应该知道它包装的组件。而对于 CoR 来说,不同的拦截器彼此之间可能一无所知。
【讨论】:
装饰者只需要知道接口,不需要任何实现。【参考方案8】:-
关键字“扩展” - 静态扩展。
装饰器模式 - 动态扩展。
责任链模式 - 仅处理命令对象
一组处理对象,这些对象彼此不认识。
【讨论】:
【参考方案9】:在阅读了四人帮的定义后,我不相信有真正的区别。 (为方便起见包括在内)
装饰器:允许动态包装对象以修改其现有职责和行为 责任链:通过将接收对象链接在一起,为多个对象提供处理请求的机会***对它们进行了一些充实,但其中一些有点武断。
装饰器通常以链接列表的形式实现。但我认为这太低级了,不能被视为模式的“一部分”。 责任链链接仅在其负责时处理数据;但确定责任和数据处理都是行为的一部分。装饰者可以轻松做到这一点。 装饰器要求您调用代理。 “纯”CoR 链接仅应在不处理数据时调用委托。前两个属性并不能真正区分模式。后两个可以,但是通常实现 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 中添加一行,如果您只想免除自己的责任,以防其他人搞砸您的设计——但为什么要让它碰运气呢?)
【讨论】:
【参考方案10】:装饰器
Decorator 模式允许将行为动态添加到单个对象。
它为子类化 提供了一种灵活的替代方法来扩展功能。即使它使用继承,它也继承自最低公分母 ( LCD ) 接口。
装饰器的 UML 图
后果:
-
通过装饰,还可以动态删除添加的功能。
装饰会在运行时向对象添加功能,这会使调试系统功能变得更加困难。
有用的链接:
When to Use the Decorator Pattern?
Decorator_pattern 来自***
decorator 来自源制作
责任链:
责任链模式是一种设计模式,由一个命令对象源和一系列处理对象组成。每个处理对象都包含定义它可以处理的命令对象类型的逻辑;其余的传递给链中的下一个处理对象
UML 图
这种模式在以下情况下更有效:
-
多个对象可以处理一个命令
事先不知道处理程序
应自动确定处理程序
希望将请求发送给一组对象,而无需明确指定其接收者
必须以动态方式指定可以处理命令的对象组
有用的链接:
Chain-of-responsibility_pattern 来自***
chain-of-responsibility-pattern 来自 oodesign
chain_of_responsibility 来自源制作
现实世界的例子:在公司中,指定的角色对处理采购请求有特定的限制。如果具有指定角色的人没有足够的权力批准采购法案,他会将命令/请求转发给拥有更大权力的继任者。该链将一直持续到命令被处理为止。
【讨论】:
以上是关于为啥我会在装饰器上使用责任链?的主要内容,如果未能解决你的问题,请参考以下文章