fuzzelogic Solutions

March 26, 2009

Chain of responsibility

Hi!

In an application I’m currently working on I have a need to process the file. The processing is determined by the type of file it is. Sounds like an ideal condidate for large complicated “if” block…. or chain of responsibility pattern. hmmmm.

COR seems like exactly what I want.. so first we need handlers ( these can handle the file ) then we need to tell each handler the next handler .. then have a means of determining if a handler can actually process the request, if not it passess this to the next handler in the chain.
Initially this is what I ended up with…

IHandler doc= new DocFileHandler();   
IHandler xl= new XLFileHandler();   
IHandler ppt= new PPTFileHandler();     // Setup the chain of responsibility.     doc.SetNextHandler(xl);    
xl.SetNextHandler(ppt);               // Throw the first handler the file request .    
doc.Handle(someFile);

It works, all goes well, but still…. all I want to do is tell the handler if it can’t handle the request to pass it on. There’s only a NEXT handler, not a list, so I used the following…

the interface ..

public interface {
void Handle(T itemToHandle);
bool CanHandle(T item);
}

and another class …

public class ChainedHandlers<T>:IHandler<T>
    {
        private readonly IHandler<T> first;
        private readonly IHandler<T> nextHandler;

        public ChainedHandlers(IHandler<T> first, IHandler<T> nextHandler )
        {
            this.first = first;
            this.nextHandler = nextHandler;
        }

        public void Handle(T itemToHandle)
        {
            if (first.CanHandle(itemToHandle))
                first.Handle(itemToHandle);
            else
            {
                nextHandler.Handle(itemToHandle);
            }
        }

        public bool CanHandle(T item)
        {
            return true;// a fake value ??
        }
    }

then …. as an extension class I created…

static public IHandler<T> add_next_handler <T>(this IHandler<T> first, IHandler<T> nextHandler )

{
 return new ChainedHandlers<T>(first, nextHandler);
 }

So far so good.. so using all this now I can do…

 var  docHandler = new DocHandler();
 docHandler
  .add_next_handler(new XlHandler())
                .add_next_handler(new PPTHandler())
                .Handle(someFile);
 

Points of interest : It’s an example of the Open/Closed Principle.  The behavior of the system can be altered by either adding handlers or changing the order of the handlers in the chain of responsibility without making any further code modifications.

Hope this helps!
Zak

3 Comments »

  1. When you add more than one handler, in the ChainedHandlers, the logic

    if (first.CanHandle(itemToHandle))
    first.Handle(itemToHandle);
    else
    {
    nextHandler.Handle(itemToHandle);
    }

    will never go to the 3rd handler. IF you have 2 handlers, it works fine.

    Comment by gsogo — May 14, 2009 @ 7:32 am

  2. Hi@gsogo.
    The chained handlers is not a collection. It always only ever has 2 internal handlers. In itself it does not do much except delegate the responsibility to the handlers. if the first handler can handle the request it does so, however if it (the first handler) can’t handle the request, it passes the request to the other handler. Handlers get chained together with the extension method add_handler.

    Hope this helps!
    Thanx

    Comment by admin — May 14, 2009 @ 1:24 pm

  3. da best. Keep it going! Thank you

    Comment by AndrewBoldman — June 4, 2009 @ 3:00 pm

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress