The Chain of Responsibility Pattern – Or how to over engineer FizzBuzz

What is FizzBuzz

Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.

Regular Solution

Most people can knock this up without even thinking about it

public class FizzBuzz
{
    public string Calculate(int number)
    {
        if (number % 15 == 0)
            return "FizzBuzz";
        if (number % 5 == 0)
            return "Buzz";
        if (number % 3 == 0)
            return "Fizz";
        return number.ToString();
    }
}
[TestFixture]
public class TestFizzBuzz
{
    [Test]
    [TestCase(5, "Buzz")]
    [TestCase(3, "Fizz")]
    [TestCase(15, "FizzBuzz")]
    [TestCase(7, "7")]
    public void TestFizzBuzzCalculate(int actual, string expected)
    {
        var sut = new FizzBuzz();
        var result = sut.Calculate(actual);
        Assert.That(result, Is.EqualTo(expected));
    }
}

The solution above, there is nothing wrong with it. I find this acceptable for something like FizzBuzz. However it does break the Open Closed principle.

The Open/Closed principle says that class should be open for extension, but closed for modification.

If there is a requirement, for example, to print out “Woof” for multiples of 4, you have to modify the FizzBuzz class. The way to solve this is to use the Chain Of Responsibility pattern. This pattern is defined as “consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain.”

To start with the chain of responsibility pattern, need a base abstract class that all the rules inherit from

public abstract class Catagorizer
{
    public Catagorizer RegisterNext(Catagorizer next)
    {
        Next = next;
        return Next;
    }

    protected Catagorizer Next { get; private set; }

    public abstract string IsSatisfiedBy(int number);
}

If we break this down, IsSatisfiedBy will be the method that each rule in the chain will call. If the rule is satisfied, then the text is returned, If the rule is not satisfied, then it will pass the execution onto the next rule in the chain.

The Next property does exactly what it says on the tin, it is the next rule to be processed. All of which is configured by the RegisterNext method which is used to specify the next rule in the chain.

Now that we have the base class, its time to work on the rule. The first rule we want is to return FizzBuzz

public class FizzBuzzCatagorizer : Catagorizer
{
    public override string IsSatisfiedBy(int number)
    {
        if (number%15 == 0)
            return "FizzBuzz";
        return Next.IsSatisfiedBy(number);
    }
}

The IsSatisfiedBy will check to see if the number passed is divisible by 5 and divisible by 3. If the number does not pass the rule, then move on to the next rule in the chain.

Here are the classes required for Fizz, and Buzz

public class BuzzCatagorizer : Catagorizer
{
    public override string IsSatisfiedBy(int number)
    {
        if (number%5 == 0)
            return "Buzz";
        return Next.IsSatisfiedBy(number);
    }
}
public class FizzCatagorizer : Catagorizer
{
    public override string IsSatisfiedBy(int number)
    {
        if (number%3 == 0)
            return "Fizz";
        return Next.IsSatisfiedBy(number);
    }
}

Now all that is required, is that if all the existing rules are not satisifed, is to just return the number.

public class PlainNumberCatagorizer : Catagorizer
{
    public override string IsSatisfiedBy(int number)
    {
        return number.ToString(CultureInfo.InvariantCulture);
    }
}

Now that all the rules are in place, we need a class that will specify the order in which the rules are to be implemented. How the order of the rules are created is important. Get the order wrong, and you will get the wrong result. Depending on the implementation, or you have the wrong tests, this is going to blow up at the wrong time.

public class CatagorizerChain
{
    private CatagorizerChain()
    {
        Head = new FizzBuzzCatagorizer();
        Head.RegisterNext(new BuzzCatagorizer())
            .RegisterNext(new FizzCatagorizer())
            .RegisterNext(new PlainNumberCatagorizer());
    }
    private Catagorizer Head { get; set; }

    public static string Calculate(int number)
    {
        return _instance.Head.IsSatisfiedBy(number);
    }

    private static readonly CatagorizerChain _instance = new CatagorizerChain();
}

As you can see, the chain is created as a singleton. In the constructor, we specify what is the first rule to be checked, and then each rule to be checked in order.

So all that needs to be called is CatagorizerChain.Calculate(number);

Now all that need to do is modify the original FizzBuzz class to call the chain, and ready to test again. All the exisitng tests should pass.

With this method in place, if there was a requirement to print “Woof” for any number that is a multiple of 4, then its easy enough to create a new class that inherits from Catagorizer, and place it in the correct locations in the rules chain.

The code can be found on github: http://github.com/thesoftwaredude/FizzBuzz

Advertisements

My musing about anything and everything

Tagged with: ,
Posted in Design Patterns, TDD

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Enter your email address to follow this blog and receive notifications of new posts by email.

Join 9 other followers

%d bloggers like this: