Question

I've recently had a real world use for the Strategy pattern. I find myself with hammer/nail syndrome where this pattern is my hammer and everything else is a nail. For kicks, I decided to try implementing FizzBuzz via the strategy pattern. Now, I know this is complete over kill. I've seen various Enterprise implementations of it, but this is my own implementation.

To my surprise and delight, this exercise turned up an interesting question: is there a standard or another pattern that works in conjunction with strategies to help you select which one to use? In my FizzBuzzStrategySelector class below, I put this logic in the Format function.

Obviously this implementation is not practical...but it might be if these Format methods actually had some real world logic to break down.

My basic question here is this: am I using the Strategy pattern correctly here?

class Program
{
    static void Main(string[] args)
    {
        FizzBuzzStrategySelector fizzBuzzFormatter = new FizzBuzzStrategySelector();

        for (int i = 1; i < 100; i++)
        {
            fizzBuzzFormatter.Format(i);
        }

        Console.ReadLine();
    }
}

public interface IOutputFormatter
{
    string FormatOutput(int value);
}

public class FizzBuzzStrategySelector
{
    public IOutputFormatter formatStrategy;

    public FizzBuzzStrategySelector() : this(new GeneralFormatter()) { }

    public FizzBuzzStrategySelector(IOutputFormatter fizzBuzzFormatStrategy) 
    {
        this.formatStrategy = fizzBuzzFormatStrategy;
    }

    public void Format(int value)
    {
        //THIS SEEMS LIKE A CODE SMELL. NOT SURE HOW TO WORK 
        //AROUND IT.
        if(value % 15 == 0)
            this.formatStrategy = new FizzBuzzFormatter();
        else if(value % 3 == 0 )
            this.formatStrategy = new FizzFormatter();
        else if(value % 5 == 0)
            this.formatStrategy = new BuzzFormatter();
        else
            this.formatStrategy = new GeneralFormatter();

        Console.WriteLine(this.formatStrategy.FormatOutput(value));
    }
}

public class GeneralFormatter : IOutputFormatter
{
    public string FormatOutput(int value)
    {
        return value.ToString();
    }
}

public class FizzBuzzFormatter : IOutputFormatter
{
    public string FormatOutput(int value)
    {
        return "FizzBuzz";
    }
}

public class BuzzFormatter : IOutputFormatter
{
    public string FormatOutput(int value)
    {
        return "Buzz";
    }
}

public class FizzFormatter : IOutputFormatter
{
    public string FormatOutput(int value)
    {
        return "Fizz";;
    }
}
Was it helpful?

Solution 2

the different output formatters are part of the strategy pattern. typically there would be an object which requires the formatter. then you can call the formatter.

class Foo
{
   public IOutputFormatter Formatter {get;set;}
}

var foo = new Foo();
foo.Formatter = new GeneralFormatter();
Console.WriteLine(foo.formatter.FormatValue("one");

foo.Formatter = new FizzBuzzFormatter();
Console.WriteLine(foo.formatter.FormatValue("one");

How the formatter is set, or which formatter is set can be the responsibility of another object.

OTHER TIPS

Since (as you are aware) the Strategy Pattern is overkill for this problem, it is hard to say what would be "good" or "bad" design. However, my gut reaction would be to move the strategy selection logic into the strategies themselves, like so:

class FizzBuzzFormatter : IOutputFormatter
{
    public bool Handles(int value) { return value.IsDivisibleBy(15); }

    public string Handle(int value) { return "FizzBuzz"; }
}

This might be a little better in terms of composability, but you still need to make sure you have a list of IOutputFormatters in the correct order. With a problem this small, you can get away with anything. With a larger problem, you need to think about it and decide for yourself.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top