1.TDD实现100door的问题

这是http://cyber-dojo.org/setup_default_start_point/show/?from=individual网站上的第一题。题目如下:

Q:100 doors in a row are all initially closed. You make 100 passes by the doors. The first time through, you visit every door and toggle the door (if the door is closed, you open it; if it is open, you close it). The second time you only visit every 2nd door (door #2,#4,#6,…)The third time every 3rd door (door #3, #6, #9, …), etc, until you only visit the 100th door.

Question: What state are the doors in after the lastpass? Which are open, which are closed?
  大致意思就是100扇连续的门最开始都是关着的,有100人会经过。第一个人会把所有的门打开。第二个人会把2的倍数的门开(如果门是关的)、关(如果门是开的)。第三个人会把3的倍数的门开(如果门是关的)、关(如果门是开的)。问100都经过之后门的状态?我贴一下的代码,用TDD实现的。
  
1、工厂类
  静态工厂类,调试相关的方法返回门的状态。我们定义这100道门为数组,0代表门关闭,1代表门打开。有个前辈说简单的方法不需要用工厂模式,这样就会使简单的问题复杂化。
  给定参数工厂DoorsFactory

package cs.doors.tdd.factory;

public class DoorsFactory {
    private static int[] doorsStation = new int[100];
    private static int count = 4;

    /** 0.最开始所有门关闭 */
    public static int[] initialDoorStation() {
        doorsStation = new int[100];
        return doorsStation;
    }

    /** 1.第一个人通过所有门打开 */
    public static int[] OnePeopleOpenDoor() {
        initialDoorStation();
        for(int i = 0; i < 100; i++) {
            if((i + 1) % 1 == 0) {
                if(doorsStation[i] == 0) {
                    doorsStation[i] = 1;
                    continue;
                }

                if(doorsStation[i] == 1) {
                    doorsStation[i] = 0;
                    continue;
                }
            }
        }
        return doorsStation;
    }


    /** 2.第二个人通过所有2倍数门反转 */
    public static int[] TwoPeopleOpenDoor() {
        OnePeopleOpenDoor();
        for(int i = 0; i < 100; i++) {
            if((i + 1) % 2 == 0) {
                if(doorsStation[i] == 0) {
                    doorsStation[i] = 1;
                    continue;
                }

                if(doorsStation[i] == 1) {
                    doorsStation[i] = 0;
                    continue;
                }
            }
        }
        return doorsStation;
    }

    /** 3.第三个人通过所有3倍数门反转 */
    public static int[] ThreePeopleOpenDoor() {
        TwoPeopleOpenDoor();
        for(int i = 0; i < 100; i++) {
            if((i + 1) % 3 == 0) {
                if(doorsStation[i] == 0) {
                    doorsStation[i] = 1;
                    continue;
                }

                if(doorsStation[i] == 1) {
                    doorsStation[i] = 0;
                    continue;
                }
            }
        }
        return doorsStation;
    }

    /** 100.第一百个人通过所有100倍数门反转 */
    public static int[] OneHundredPeopleOpenDoor() {
        ThreePeopleOpenDoor();
        int num = 100 - 3;
        while(num > 0) {
            for(int i = 0; i < 100; i++) {
                if((i + 1) % count == 0) {
                    if(doorsStation[i] == 0) {
                        doorsStation[i] = 1;
                        continue;
                    }
                    if(doorsStation[i] == 1) {
                        doorsStation[i] = 0;
                        continue;
                    }
                }
            }
            count++;
            num--;

        }
        return doorsStation;
    }
}

2、Mock测试
  给定参数是int num,doorsGiven 是预期的值,而doorsReturn 是调用实际方法返回的值。

package cs.doors;

import java.util.Arrays;

import org.junit.Assert;
import org.junit.Test;
import org.junit.internal.runners.JUnit4ClassRunner;
import org.junit.runner.RunWith;

import cs.doors.tdd.factory.DoorsFactory;

@RunWith(JUnit4ClassRunner.class)
public class DoorsProblemTest {
    @Test
    public void 初始化_所有门关闭() {
        //given
        int num = 0;
        int[] doorsGiven = DoorsFactory.initialDoorStation();
        DoorsProblem doorsProblem = new DoorsProblem();

        //when
        int[] doorsReturn = doorsProblem.OneHundredDoorsDemo(num);

        //then
        Assert.assertArrayEquals(doorsGiven, doorsReturn);
    }

    @Test
    public void 第一个人_所有门打开() {
        //given
        int num = 1;
        int[] doorsGiven = DoorsFactory.OnePeopleOpenDoor();
        DoorsProblem doorsProblem = new DoorsProblem();

        //when
        int[] doorsReturn = doorsProblem.OneHundredDoorsDemo(num);

        //then
        Assert.assertArrayEquals(doorsGiven, doorsReturn);
    }

    @Test
    public void 第二个人_对2倍数门操作() {
        //given
        int num = 2;
        int[] doorsGiven = DoorsFactory.TwoPeopleOpenDoor();
        DoorsProblem doorsProblem = new DoorsProblem();

        //when
        int[] doorsReturn = doorsProblem.OneHundredDoorsDemo(num);

        //then
        Assert.assertArrayEquals(doorsGiven, doorsReturn);
    }

    @Test
    public void 第三个人_对3倍数门操作() {
        //given
        int num = 3;
        int[] doorsGiven = DoorsFactory.ThreePeopleOpenDoor();
        DoorsProblem doorsProblem = new DoorsProblem();

        //when
        int[] doorsReturn = doorsProblem.OneHundredDoorsDemo(num);

        //then
        Assert.assertArrayEquals(doorsGiven, doorsReturn);
    }

    @Test
    public void 第一百个人_对100倍数门操作() {
        //given
        int num = 100;
        DoorsProblem doorsProblem = new DoorsProblem();
        int[] doorsGiven = DoorsFactory.OneHundredPeopleOpenDoor();

        /** 打印 门 最终的状态 */
        System.out.println(Arrays.toString(doorsGiven));

        //when
        int[] doorsReturn = doorsProblem.OneHundredDoorsDemo(num);

        /** 打印 门 最终的状态 */
        System.out.println(Arrays.toString(doorsReturn));

        //then
        Assert.assertArrayEquals(doorsGiven, doorsReturn);
    }
}

3、主要方法
  其实这里应该就是实用代码,上述的代码都是为了TDD。TDD的优势很明显,遇到不会的题目小步前进,在TDD中寻找规律、发现规律,进而解决问题。由于比较忙,只会给出代码,以后可能就会具体分析给童鞋们,欢迎留言相互交流。

package cs.doors;

public class DoorsProblem {
    int[] doors = new int[100];
    int count = 1;

    public int[] OneHundredDoorsDemo(int num) {
        initialDoors();
        return peopleOpenDoors(num);
    }

    public void initialDoors() {
        for(int i = 0; i < 100; i++) {
            doors[i] = 0;
        }
    }

    public int[] peopleOpenDoors(int num) {
        while(num > 0) {
            for(int i = count - 1; i < 100; i = i + count) {
                if(doors[i] == 0) {
                    doors[i] = 1;
                    continue;
                }
                if(doors[i] == 1) {
                    doors[i] = 0;
                    continue;
                }
            }
            count++;
            num--;
        }
        return doors;
    }

}

注意:很多时候我们完成了代码只是实现了功能,接着就应该重构,其实重构发生在我们TDD整个生命周期,使用重构看能否使代码量更加简洁。当然,上述代码是重构完之后的。

    原文作者:舞伴问题
    原文地址: https://blog.csdn.net/u010986518/article/details/82352880
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞