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.