Fizz Buzz Kata

Using Chain of Responsibility

A developer I was coaching and I were going to do a coding dojo for developers on other teams to introduce them to TDD.

We decided Fizz Buzz was the simplest. We could demo it in 20-30 minutes and then they could try to replicate the process.

In order to be prepared, I practiced the kata a couple of times. One time for fun I refactored it to use Chain of Responsibility and thought I’d share.


// The main class
public class FizzBuzz {

	public String countTo(int i) {
		return countTo(1, i);
	}

	String countTo(int from, int to) {
		StringBuilder sb = new StringBuilder();
		sb.append(String.valueOf(from));
		for (int i = from + 1; i <= to; i++)
			sb.append(Chain.get(i));
		return sb.toString();
	}

}

public abstract class Chain {
	// order is important here
	private static Chain[] links = new Chain[] {
		new FizzBuzz(), 
		new Fizz(),
		new Buzz(),
		new Number()};
	
	public static String get(int i) {
		for (Chain link : links) {
			if (link.respondsTo(i))
				return link.respond(i);
		}
		return "";
	}
	
	abstract protected String respond(int i);
	abstract protected boolean respondsTo(int i);
	
	
	private static final class Number extends Chain {

		@Override
		protected String respond(int i) {
			return "," + i;
		}

		@Override
		protected boolean respondsTo(int i) {
			return true;
		}
		
	}
	
	private static final class Buzz extends Chain {

		@Override
		protected String respond(int i) {
			return ",Buzz";
		}

		@Override
		protected boolean respondsTo(int i) {
			return i % 5 == 0;
		}
		
	}
	
	private static final class Fizz extends Chain {

		@Override
		protected String respond(int i) {
			return ",Fizz";
		}

		@Override
		protected boolean respondsTo(int i) {
			return i % 3 == 0;
		}
		
	}
	
	private static final class FizzBuzz extends Chain {

		@Override
		protected String respond(int i) {
			return ",FizzBuzz";
		}

		@Override
		protected boolean respondsTo(int i) {
			return i % 15 == 0; 
		}
		
	}
}

@RunWith(JUnitParamsRunner.class)
public class FizzBuzzTest {

    private FizzBuzz fizzBuzz;

    @Before
    public void setUp() throws Exception {
        fizzBuzz = new FizzBuzz();
    }

    @Test
    @Parameters(method = "parameters")
    public void canCountTo(int from, int to, String result) throws Exception {
        assertThat(fizzBuzz.countTo(from, to), is(result));
    }

    private Object parameters() {
        return new Object[] {
                new Object[] {1, 2, "1,2"},
                new Object[] {1, 3, "1,2,Fizz"},
                new Object[] {1, 5, "1,2,Fizz,4,Buzz"},
                new Object[] {1, 6, "1,2,Fizz,4,Buzz,Fizz"},
                new Object[] {1, 10, "1,2,Fizz,4,Buzz,Fizz,7,8,Fizz,Buzz"},
                new Object[] {1, 15, "1,2,Fizz,4,Buzz,Fizz,7,8,Fizz,Buzz,11,Fizz,13,14,FizzBuzz"},
                new Object[] {28, 31, "28,29,FizzBuzz,31"}
        };
    }
}

I refactored Chain to have isFizz(i) and isBuzz(i) so I could use isFizz(i) && isBuzz(i) in FizzBuzz, but I didn’t like the parent knowing details of it’s children just to remove a little conditional duplication.

Published on