Why would I ever use a Chain of Responsibility ove

2020-02-02 04:25发布

I'm just reading up on the Chain of Responsibility pattern and I'm having trouble imagining a scenario when I would prefer its use over that of decorator.

What do you think? Does CoR have a niche use?

11条回答
兄弟一词,经得起流年.
2楼-- · 2020-02-02 04:49

The fact that you can break the chain at any point differentiates the Chain of Responsibility pattern from the Decorator pattern. Decorators can be thought of as executing all at once without any interaction with the other decorators. Links in a chain can be thought of as executing one at a time, because they each depend on the previous link.

Use the Chain of Responsibility pattern when you can conceptualize your program as a chain made up of links, where each link can either handle a request or pass it up the chain.

When I used to work with the Win32 API, I would sometimes need to use the hooking functionality it provides. Hooking a Windows message roughly follows the Chain of Responsibility pattern. When you hooked a message such as WM_MOUSEMOVE, your callback function would be called. Think of the callback function as the last link in the chain. Each link in the chain can decide whether to throw away the WM_MOUSEMOVE message or pass it up the chain to the next link.

If the Decorator pattern had been used in that example, you would have been notified of the WM_MOUSEMOVE message, but you would be powerless to prevent other hooks from handling it as well.

Another place the Chain of Command pattern is used is in game engines. Again, you can hook engine functions, events, and other things. In the case of a game engine, you don't want to simply add functionality. You want to add functionality and prevent the game engine from performing its default action.

查看更多
不美不萌又怎样
3楼-- · 2020-02-02 04:50

Well I can think of 2 situations:

  • You don't have a core object, i.e. you don't know what to do with the request after it passed all the layers/filters. (something like an aspect like interceptor chains that don't really care where the request ends).
  • You need to selectively apply some pre or post processing to the request. Not in a general enhancement form as the decorator does. i.e. Filters may or maynot handle a specific request but adding a decorator always enhances your object with some functionality.

Can't think of any more right now, would love to hear more in this topic.

查看更多
萌系小妹纸
4楼-- · 2020-02-02 04:51

Decorator is used when you want to add functionality to an object.

COR is used when one of many actors might take action on an object.

A particular Decorator is called to take an action, based on the type; while COR passes the object along a defined chain until one of the actors decides the action is complete.

COR might be used when there are multiple levels of escalation to different handlers -- for instance, a call center where the customer's value to the company determines if the call goes to a particular level of support.

查看更多
爷、活的狠高调
5楼-- · 2020-02-02 04:54

I'd say that a Chain of Responsibility is a particular form of Decorator.

查看更多
该账号已被封号
6楼-- · 2020-02-02 04:59

The difference between these patterns is not related to when or how the chain can be broken (which assumes a chain) or in when the extra behaviour is executed. They are related in that they both use composition in favour of inheritance to provide a more flexible solution.

The key difference is that a decorator adds new behaviour that in effect widens the original interface. It is similar to how normal extension can add methods except the "subclass" is only coupled by a reference which means that any "superclass" can be used.

The COR pattern can modify an existing behaviour which is similar to overriding an existing method using inheritance. You can choose to call super.xxx() to continue up the "chain" or handle the message yourself.

So the difference is subtle but an example of a decorator should help:

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();
    }
}

You can see that we can compose a walking, barking animal... or in fact add the ability to bark to any animal. To use this extra behaviour directly we would need to keep a reference to the BarkingAnimal decorator.

All BarkingAnimal's also bark once before eating which has changed existing functionality and so is similar to a COR. But the intent is not the same as COR i.e. to find one Animal of many that will eat the food. The intent here is to modify the behaviour.

You could imagine a COR being applied to find a human that will take the animal for a walk. This could be implemented as a linked list like chained above or as an explicit List... or whatever.

Hope this is reasonably clear!

John

查看更多
兄弟一词,经得起流年.
7楼-- · 2020-02-02 04:59

I think the situations to apply these two patterns are different. And by the way, for decorator pattern, the decorator should know the component which it wrapped. And for CoR, the different interceptors could know nothing of each other.

查看更多
登录 后发表回答