in

ASP.NET Weblogs

J e r o e n ' s   w e b l o g

June 2005 - Posts

  • A slightly modified Chain of Responsibility

    Recently I implemented a Chain of Responsibility in C# and decided to modify it a bit for my application, since the original pattern favours object hierarchies heavily and I wanted to use it in a flat context. With flat I mean that I have a bunch of handlers and I don't have a fixed order for going through the chain, I just want any handler capable of handling the request to do it. Since objects usually know about their parents in hierarchies, the pattern puts the responsibility for chaining to the next possible handler in the objects. This is fine in those hierarchies, but makes it very error-prone in another context, where you have to do all the chaining setup by hand (like passing a reference to the previous handler you added to the next one). To remedy this, I've added some static functionality to a Handler baseclass and the result is cleaner code in non-hierarchical chains. Below is my implementation of the Handler baseclass:

      public class Handler
      {
        private Handler _successor;
        private static Handler _rootHandler;
        public static Handler RootHandler
        {
          get { return _rootHandler; }
        }

        public static void Add(Handler handler)
        {
          if(null == _rootHandler)
          {
            _rootHandler = handler;
          }
          else
          {
            Handler currentHandler = _rootHandler;
            while(null != currentHandler._successor)
            {
              currentHandler = currentHandler._successor;
            }
            currentHandler._successor = handler;
          }
        }

        public virtual void Handle(int request)
        {
          if(null != _successor)
          {
            _successor.Handle(request);
          }
        }
      }

    Implementing the concrete handlers is no different from the original pattern. Just override the Handle method and if you decide not to handle the request, call the base implementation to forward it to the next in the chain. Below is an example:

      public class SmallHandler : Handler
      {
        public override void Handle(int request)
        {
          if(10 > request)
          {
            // handle the request
          }
          else
          {
            base.Handle(request);
          }
        }
      }

    To add a handler to the list, just call the static Handler.Add method and pass a reference to an instance of a concrete handler to it. Finally, to enter the chain, just call the Handle method on the static RootHandler property:

      Handler.Add(new SmallHandler());
      Handler.Add(new MediumHandler());
      Handler.Add(new BigHandler());
      Handler.RootHandler.Handle(someRequest);

    I realize that for these scenarios, I could just have implemented a list to store handlers and iterate through it every time I want to call a handler. To make that work however you need to put a return value on the Handle method to communicate whether the request was handled or not (since there's no other way to determine whether it handled the request) and this approach kept the handlers compatible with a regular Chain of Responsibility.

More Posts