题目内容:
FizzBuzzWhizz
你是一名体育老师,在某次课距离下课还有五分钟时,你决定搞一个游戏。此时有100名学生在上课。游戏的规则是:
1. 你首先说出三个不同的特殊数,要求必须是个位数,比如3、5、7。
2. 让所有学生拍成一队,然后按顺序报数。
3. 学生报数时,如果所报数字是第一个特殊数(3)的倍数,那么不能说该数字,而要说Fizz;如果所报数字是第二个特殊数(5)的倍数,那么要说Buzz;如果所报数字是第三个特殊数(7)的倍数,那么要说Whizz。
4. 学生报数时,如果所报数字同时是两个特殊数的倍数情况下,也要特殊处理,比如第一个特殊数和第二个特殊数的倍数,那么不能说该数字,而是要说FizzBuzz, 以此类推。如果同时是三个特殊数的倍数,那么要说FizzBuzzWhizz。
5. 学生报数时,如果所报数字包含了第一个特殊数,那么也不能说该数字,而是要说相应的单词,比如本例中第一个特殊数是3,那么要报13的同学应该说Fizz。如果数字中包含了第一个特殊数,那么忽略规则3和规则4,比如要报35的同学只报Fizz,不报BuzzWhizz。
5. 学生报数时,如果所报数字包含了第一个特殊数,那么也不能说该数字,而是要说相应的单词,比如本例中第一个特殊数是3,那么要报13的同学应该说Fizz。如果数字中包含了第一个特殊数,那么忽略规则3和规则4,比如要报35的同学只报Fizz,不报BuzzWhizz。
现在,我们需要你完成一个程序来模拟这个游戏,它首先接受3个特殊数,然后输出100名学生应该报数的数或单词。比如,
输入
3,5,7
输出(片段)
1
2
Fizz
4
Buzz
Fizz
Whizz
8
Fizz
Buzz
11
Fizz
1
2
Fizz
4
Buzz
Fizz
Whizz
8
Fizz
Buzz
11
Fizz
Fizz
Whizz
FizzBuzz
16
17
Fizz
19
Buzz
…
Whizz
FizzBuzz
16
17
Fizz
19
Buzz
…
一直到100
5.1节前,在部门内部安排大伙写了一下,很多童鞋子也写了,感觉用JAVA写出来的,没有比较理想的。后来就借这个题叫大伙坐一起,一起写了一下。代码都属临场发挥,没过多细想,应该还有很多重构空间,因为一来本来没有投简历意向,二来时间也不是很足够,所以,在此就不追求极致了。与大伙分享一下,重在思想,欢迎指正。
拿一个问题,我们首先分析问题的本质,本题的本质就是处理数字,OK.那我们就先定义一个接口:
public interface NumberHandler {
String doHandler(Integer num);
}
我们继续分析,其实有2种处理数据的方式,一种是倍数,一种是包含关系,所以我们定义了2个具体实现类:ContainHandler,MutipluHandler。
经过简单重构以后,提取出了一个DefaultHandler。代码如下:
public abstract class DefaultHandler implements NumberHandler {
/**输入值*/
protected Integer value;
/**输出单词*/
protected String word;
public DefaultHandler(Integer value, String word) {
this.value = value;
this.word = word;
}
public abstract String doHandler(Integer num);
}
public class MutipluHandler extends DefaultHandler{
public MutipluHandler(Integer value, String word) {
super(value, word);
}
@Override
public String doHandler(Integer num) {
if(num % value==0){
return word;
}
return null;
}
}
public class ContainHandler extends DefaultHandler implements Dictatorial{
public ContainHandler(Integer value, String word) {
super(value, word);
}
@Override
public String doHandler(Integer num) {
if(num.toString().contains(value.toString())){
return word;
}
return null;
}
}
你是不是发现了ContainHandler还实现了一个Dictatorial接口,这个其实是后来加上去的,因为一旦满足ContainHandler处理条件,将不会被其它处理器处理,所以他是一个独占式的。因此定义了Dictatorial一个标识接口:
/**
* Created by Administrator on 2014/5/7.
* 独断处理,标识接口
*/
public interface Dictatorial {
}
剩下要做的就是需要一个处理器链,来挨个调用处理逻辑:
public class FilterChain {
private static LinkedList<NumberHandler> handlerList = new LinkedList<NumberHandler>();
public void addHandler(NumberHandler handler){
if(handler instanceof Dictatorial){
handlerList.addFirst(handler);
}else{
handlerList.add(handler);
}
}
public void doFilter(Integer num){
String result = "";
boolean flag = true;
for(NumberHandler handler: handlerList){
//独断处理
if(!flag) break;
String temp = handler.doHandler(num);
if(temp != null){
result+= temp;
if(handler instanceof Dictatorial){
flag = false;
}
}
}
System.out.println(result == "" ? num : result);
}
}
最后就是测试类:
public class TestRunner {
public static void main(String[] args) {
//create resource
FilterChain chain = new FilterChain();
MutipluHandler h1 = new MutipluHandler(3,"Fizz");
MutipluHandler h2 = new MutipluHandler(5,"Buzz");
MutipluHandler h3 = new MutipluHandler(7,"Whizz");
ContainHandler h4 = new ContainHandler(3,"Fizz");
chain.addHandler(h4);
chain.addHandler(h1);
chain.addHandler(h2);
chain.addHandler(h3);
for(int i= 1; i<=100; i++){
chain.doFilter(i);
}
}
}
其实在解决这个问题的时候,大致过程是这样:
1.定义接口
2.给出2个实现类,支持3,5,7
3.重构2个实现类,将3,5,7做到可以灵活配置。
4.定义FilterChain,先满足倍数处理
5.处理包含这种独占式处理器,定义标识接口,重构FilterChain