关于Thoughtworks在拉勾的那个面试题

题目内容:

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。
 
现在,我们需要你完成一个程序来模拟这个游戏,它首先接受3个特殊数,然后输出100名学生应该报数的数或单词。比如,
 
输入
3,5,7
输出(片段)

1
2
Fizz
4
Buzz
Fizz
Whizz
8
Fizz
Buzz
11
Fizz
Fizz
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



你可能感兴趣的:(关于Thoughtworks在拉勾的那个面试题)