为什么我会在装饰师身上使用责任链?

Geo*_*uer 70 oop design-patterns decorator chain-of-responsibility

我只是阅读了责任链模式,当我更喜欢使用装饰器时,我很难想象一个场景.

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

Wil*_*del 68

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

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

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

如果在该示例中使用了Decorator模式,则会收到WM_MOUSEMOVE消息的通知,但是您也无法阻止其他挂钩处理它.

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


Joh*_*son 17

这些模式之间的差异与链的何时或如何被破坏(假设链)或何时执行额外行为无关.它们的相关之处在于它们都使用组合来支持继承,以提供更灵活的解决方案.

关键的区别在于装饰器添加了新的行为,实际上扩大了原始界面.它类似于普通扩展可以添加方法的方式,除了"子类"仅通过引用耦合,这意味着可以使用任何"超类".

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以看到我们可以组成一只行走的,吠叫的动物......或者实际上增加了对任何动物吠叫的能力.要直接使用这个额外的行为,我们需要保持对BarkingAnimal装饰器的引用.

所有BarkingAnimal在吃之前都会吠叫一次,这改变了现有的功能,因此类似于COR.但意图与COR不同,即找到一个会吃掉食物的动物.这里的目的是修改行为.

你可以想象一个COR应用于寻找一个将动物带走的人类.这可以作为chained上面的链接列表实现,也可以作为显式List ...或其他任何方式实现.

希望这个相当清楚!

约翰

  • 这个答案让我终于意识到我理解这些模式的方式是错误的!我在结构上考虑了书中提出的类图,其中责任链具有抽象的父类和后继类.但GoF指出,你也可以使用mixin继承,在这种情况下,类图看起来完全相同.但意图和行为差异的关键因素,特别是DECORATOR如何拓宽界面,至关重要.很好的答案. (3认同)

Bri*_*ian 13

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

VS

装饰

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

我会说它会围绕事情发生的顺序.如果你链接它们,将沿着链调用.对于装饰者,您无法保证此订单,只能附加其他责任.


tro*_*skn 11

我要说责任链装饰者的一种特殊形式.


Rag*_*czy 8

当您想要向对象添加功能时,使用Decorator.

当许多actor中的一个可能对某个对象采取操作时使用COR.

特定装饰被称为采取动作,基于该类型; COR沿着定义的链传递对象,直到其中一个角色决定动作完成.

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

  • 但是装饰器是一种不同的模式 - 使用COR,对象从演员传递到演员,直到有人说完成了动作; 使用装饰器,动作将在一个特定类的实现上执行. (3认同)