Is HashMap in a chain of responsibility an abuse of the pattern?

407 views Asked by At

I've seen an example implementation of the CoR pattern using a HashMap as the object that is passed down the chain, possibly with new content being added to it by handlers; an outline of the code below:

class HandlerImpl implements Handler {

     Handler next;

     void handle(HashMap context) {
         // do handler logic, perhaps adding new stuff to "context"
         if (next != null)
             next.handle();
     }
 }

It's tempting to use, as handlers may enhance the context with new information that may be used by following handlers without repeating the code. On the other hand, handlers become dependent on one another — they're still loosely coupled, but still, their order becomes increasingly important.

Is this code smell? If we find out that we cannot do with the CoR pattern without supplementing the context object with new information, what's the right pattern to use in such case?

2

There are 2 answers

0
Costi Ciudatu On BEST ANSWER

I don't think passing a context down the chain is a violation of the pattern.

The servlet filter is usually used as an example for the CoR pattern, and filters are free to add/remove attributes on a shared request object or even to wrap the request in a new object in order to intercept any operation performed by subsequent filters or servlets.

0
Jon Skeet On

It depends what your "handler" is meant to be doing. One alternative is to change it into a "pipeline" which declares what input it requires, and what its output will be. The output could be the same type - possibly with modifications of the input objects - or it could be some transformation. That transformation could just add information, or do something entirely different. If information just needs to be added, that can be done fairly easily using composition.

That way each handler is tightly coupled (and explicit) in terms of what data it requires/produces - but it's loosely coupled in terms of what will produce and consume that data.

Basically the "best approach" will depend on:

  • What you're trying to do
  • What language/platform you're using (Does it have an immutable thrust? Does it have static typing, and generics?)