Jan 1 2010

Follow the chain of command

Have you ever seen those seemingly endless if -> else if -> else if -> ... -> else if statements? Sure you have! You have possibly even written one or two, but confessions are not really necessary. In some cases, all we are trying to do is subject an object to a line of inspection and then branch based on those results. This may be fine, but if you find yourself continuously adding new else if items to the end of that statement, there may be another pattern that is more appropriate. Enter the chain-of-responsibility pattern, What is that?  

In Object Oriented Design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains a set of logic that describes the types of command objects that it can handle, and how to pass off those that it cannot to the next processing object in the chain. A mechanism also exists for adding new processing objects to the end of this chain.
- Wikipedia (http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern)

The description sounds somewhat complicated, so a walkthrough can make this a lot easier to understand. Lets start with a simple example. Say we want to have a bunch of independent modules inspect a payload to ensure it contains something. If we exit the end of the chain with no exceptions, it passes; otherwise it fails. The first thing we need to do is define the structure of each link in our chain.

public interface ILink
{
    //Holds the next link in the chain
    ILink SuccessorLink { get; set; }
    void Inspect(object payload);
}

Any module that is a candidate for this chain will need to implement this interface and honor the flow control by passing valid payloads down the chain and short-circuiting others.  Beyond that, each module can do whatever they need. Next we need some links that implement our interface. Both of the below sample modules will simply inspect the payload and either pass it down the chain or short-curcuit via exception.  In reality, using exceptions is not the most efficiant way to do this but it suites the sample. You can use any number of methods to handle the short-curcuiting process, but not calling the Inspect method is enough to end processing. 

public sealed class LinkTypeA : ILink
{
    #region ILink Members
    public ILink SuccessorLink { get; set; }
    public void Inspect(object payload)
    {
        if (payload.ToString().Contains("A"))
        {
            if (SuccessorLink != null)
            {
                SuccessorLink.Inspect(payload);
            }
        }
        else
        {
            throw new NotSupportedException("The payload is not supported");
        }
    }
    #endregion
}

public sealed class LinkTypeB : ILink
{
    #region ILink Members
    public ILink SuccessorLink { get; set; }

    public void Inspect(object payload)
    {
        if (payload.ToString().Contains("B"))
        {
            if (SuccessorLink != null)
            {
                SuccessorLink.Inspect(payload);
            }
        }
        else
        {
            throw new NotSupportedException("The payload is not supported");
        }
    }
    #endregion
}
 

Next we need some infrastructure to build and manage the chain. Normally I like to approach this process using some kind of Factory pattern driven by configuration meta-data. For this sample we will just create a simple chain manager to demonstrate how to build a chain.

public static class ChainManager
{
    public static ILink Chain { get; private set; }
    public static void AddLinkToChain(ILink link)
    {
        if (Chain == null)
        {
            Chain = link;
        }
        else
        {
            AppendLinkToChain(link, Chain);
        }
    }

    private static void AppendLinkToChain(ILink link, ILink chain)
    {
        if (link == null) return;

        if (chain.SuccessorLink != null)
        {
            AppendLinkToChain(link, chain.SuccessorLink);
        }
        else
        {
            chain.SuccessorLink = link;
        }
    }
}

With the ChainManager available, we just need to initialize the chain and then submit a payload for processing:

ILink linkA = new LinkTypeA();
ILink linkB = new LinkTypeB();
ChainManager.AddLinkToChain(linkA);
ChainManager.AddLinkToChain(linkB);

try
{
    ChainManager.Chain.Inspect("ABC");
    //The payload passed all checks
}
catch (NotSupportedException)
{
    //The payload failed a check
}

One of the great things about this pattern is that you can easily add and remove links, and each link can represent a completely seperate area of concern. When building the chain, you can also order items so they execute in the most efficient manner. This involves placing links that are more likely to lead to short-circuiting high in the link chain. Additionally, since all the links are seperate areas of concern, it makes these easy to test in isolation. 

Give it a think...  Worth considering for some architectures.  Enjoy! 

Tags:

Comments

1.
trackback DotNetKicks.com says:

Follow the chain of command

You've been kicked (a good thing) - Trackback from DotNetKicks.com

2.
Austin condos Austin condos United States says:

Tried to autotranslate you situation not understand the work any hope deutsch variant?



Regards
Marr



3.
Dudley Shewmaker Dudley Shewmaker United States says:

This is a good write-up, I was wondering if I could use this piece of writing on my website, I will link it back to your website though. If this is a problem please let me know and I will take it down right away.

4.
Jon Mattan Jon Mattan United States says:

Im glad I found this blog site, I couldnt discover any knowledge on this topic prior to. Also run a niche site and for anyone who is ever interested in a little bit of visitor writing for me if possible feel free to let me know, im always look for people to check out my web site. Please stop by and leave a comment sometime!

5.
Nadia Clay Nadia Clay United States says:

This is a good piece, I was wondering if I could use this summary on my website, I will link it back to your website though. If this is a problem please let me know and I will take it down right away.

6.
Ami Knoop Ami Knoop United States says:

Wonderful site, where did you come up with the info in this posting? Im happy I found it though, ill be checking back soon to see what other articles you have.

7.
Adriane Charo Adriane Charo Turkey says:

Pretty nice post. I have sincerely enjoyed reading your website posts. I have been visiting blogs and sites in related manner recently and i have to state you have a nice design and content. Any way I will be subscribing to your feed and I hope you post more regularly.

8.
Walton Piccinini Walton Piccinini United States says:

Hi i am so pleased I found your blog, I really found you by mistake, while I was searching Yahoo for something else, At Any Rate I am here now and would just like to say thank you for a wonderful blog posting and a all round intriguing blog (I also love the theme/design), I do not have time to read it all at the right now but I have bookmarked it and also added your RSS feeds.

9.
Phillip Radman Phillip Radman United States says:

This is a useful post, but I was wondering how do I suscribe to the RSS feed?

10.
Ike Hemmerling Ike Hemmerling United States says:

Hi thanks a lot for a perceptive post, I actually found your blog by mistake while looking on Goole for something else closely related, anyhow before i ramble on too much i would just like to state how much I enjoyed your post, I have bookmarked your site and also taken your RSS feed, Once Again thanks for the blog post keep up the good work.

11.
Jamila Swiss Jamila Swiss United Kingdom says:

Thank you for the time you put into sharing the article with us. Great post

12.
Lionel Gabisi Lionel Gabisi United States says:

This is one technology that I would love to be able to use for myself. It’s definitely a cut above the rest and I can’t wait until my provider has it. Your insight was what I needed. Thanks

13.
Lionel Gabisi Lionel Gabisi United States says:

Heard about this site from my friend. He pointed me here and told me I’d find what I need. He was right! I got all the questions I had, answered. Didn’t even take long to find it. Love the fact that you made it so easy for people like me. More power

14.
Ressie Quashie Ressie Quashie United States says:

This is a good piece, I was wondering if I could use this post on my website, I will link it back to your website though. If this is a problem please let me know and I will take it down right away. % BLOGTITLE %

15.
Lyman Adil Lyman Adil United States says:

I have read a few of the articles on your website now, and I really like your style of blogging. I added it to my favorites blog page list and will be checking back soon. Please check out my site as well and let me know what you think.

Comments are closed