设计模式之命令(State)模式

     状态模式是在程序开发时,经常用到的模式。如果没有应用过,而实现业务功能。那你也一定是按照状态模式的路子走的,只不过你没有感觉到而已。它的实现,是要根据对象的内部状态变化,而自动执行相应的功能。
费话就不说了,请看一下源代码,这也是我研究设计模式时看到的一个例子,把其翻译成中文,使个位网友能够看懂些,由于水平有限,只能达到这样,还希望网友多指证,也算是抄来的哈哈,谢谢啊。

public class GumballMachine {
	//这就是那4个状态,每个状态都用一个不同的整数代表,他们符合状态图   
    final static int SOLD_OUT = 0;      //糖果售完状态   
    final static int NO_QUARTER = 1;    //没有钱状态   
    final static int HAS_QUARTER = 2;   //有钱状态   
    final static int SOLD = 3;      //售出糖果   
    //这个实例变量跟踪当前状态,一开始被设为"糖果售完",因为糖果机安装时是没有装糖果的   
    int state = SOLD_OUT;   
    int count = 0;  //这个变量用来追踪机器内的糖果数目   
    //构造器初始糖果库存量当做参数,如果库存不为0的话,机器就进入"没有钱"的状态,等着你向里投钱
    public GumballMachine(int count) {   
        this.count = count;   
        if (count > 0) {   
            state = NO_QUARTER;   
        }   
    }   
    
  //当把钱投入进来,就会执行这里   
    public void insertQuarter() {   
        if (state == HAS_QUARTER) {   
            //如果此时的状态为有钱状态,则通知顾客   
            System.out.println("你不能再向糖果机里投钱了");   
        } else if (state == NO_QUARTER) {   
            //如果是在"没有25分钱"的状态下,我们就接受25分钱,并将状态转换到"有25分钱"   
            state = HAS_QUARTER;   
            System.out.println("你可以向糖果机里投钱");   
        } else if (state == SOLD_OUT) {   
            //如果糖果售完,就拒绝收钱   
            System.out.println("糖果已经卖完,不能再向里投钱了");   
        } else if (state == SOLD) {   
            //如果顾客买到糖果,就需要稍等下,好让状态转换完毕,恢复到"没有25分钱"的状态
            System.out.println("已向你卖出一个糖果,请稍等,再向里投钱。");   
        }   
    }   
    //现在,如果顾客试着退回25分钱...   
    public void ejectQuarter() {   
        if (state == HAS_QUARTER) {   
            //如果有25分钱,就退钱,回到"没有25分钱"的状态   
            System.out.println("退钱成功");   
            state = NO_QUARTER;   
        } else if (state == NO_QUARTER) {   
            //如果没有25分钱,当然不能退回   
            System.out.println("没有钱,你不能退钱");   
        } else if (state == SOLD) {   
            //如果顾客已经转动手柄,就不能退钱了,他已经拿到糖果了
        	state = NO_QUARTER;
            System.out.println("对不起,糖果已经卖出不能退钱。");   
        } else if (state == SOLD_OUT) {   
            //如果糖果售完,就不可能接受25分钱,当然也不可能退钱   
            System.out.println("对不起,糖果已经卖完不能退钱");   
        }   
    }   
  //顾客试着转动手柄...   
    public void turnCrank() {   
        if (state == SOLD) {   
            //别想骗过机器拿2次糖果   
            System.out.println("不能再给你了");   
        } else if (state == NO_QUARTER) {   
            //我们需要先投入25分钱   
            System.out.println("你没有投钱糖果不能卖给你");   
        } else if (state == SOLD_OUT) {   
            //没有糖果了   
            System.out.println("糖果机中没有糖果了,你不能进行交易。");   
        } else if (state == HAS_QUARTER) {   
            //成功!他拿到糖果了.改变状态到"售出糖果",然后调用机器的dispense()方法   
            System.out.println("请稍等,一会糖果你就可以拿到了...");   
            state = SOLD;   
            dispense();   
        }   
    }   
    //发放糖果   
    public void dispense() {   
        if (state == SOLD) {   
            //我们正在"售出糖果"状态   
            System.out.println("一个糖果将从这里出来....");   
            count = count - 1;   
            //我们在这里处理"糖果售完"的情况   
            if (count == 0) {//最后一颗,将机器设置到"糖果售完"状态   
                System.out.println("库存为零!");   
                state = SOLD_OUT;   
            } else {    //否则回到"没有25分钱"的状态   
                state = NO_QUARTER;   
            }   
        } else if (state == NO_QUARTER) {   //以下都不应该发生,但如果顾客这么做了,得到的应该是错误消息而不是糖果   
            System.out.println("你需要向糖果机里投钱。。");   
        } else if (state == SOLD_OUT) {   
            System.out.println("糖果已经卖没了");   
        } else if (state == HAS_QUARTER) {   
            System.out.println("请您稍等交易还没有结束。");   
        }   
    }   

}

 

测试就来自已写吧,我提供个思路,就是页面提供几个开关,即按纽、checkbox等在它们的单击事件上GumballMachine实例的内部状态改变。然后看其变化,就可以了。

大家看没看出来,这段代码还有一些“怪的味道”呀,这时如果业务变化了,如果客户是一个中奖的用户,需要糖果机吐出两块糖果,怎么办?,是不是还得在各个方法中把这个状态给加上呀,又得加一个if语句呢,这是一个业务发生了变化,如果业务要无限的变化下去,程序员是不是都要疯了,哈哈。所以要对其进行重构了。

要把这几个状态抽象出来。想到这里看一下代码就明白了。

public interface State {
	//投钱的状态
	public void insertQuarter();
	//退钱的状态
	public void ejectQuarter();
    //按下按纽状态
	public void turnCrank();
    //发放物品状态
	public void dispense();

}

下面是几个实现这个状态接口的实现类。

 

public class HasQuarterState implements State{
	GumballMachineTwo gumballMachine;   
    //增加一个随机数产生器,产生10%的机会   
    Random randomWinner = new Random(System.currentTimeMillis());   
    public HasQuarterState(GumballMachineTwo gumballMachine) {   
        this.gumballMachine = gumballMachine;   
    }   
    public void insertQuarter() {   //这是一个对当前状态不恰当的动作   
        System.out.println("不能再投钱了,已经有钱了。");   
    }   
    
    public void ejectQuarter() {    //退钱并转换状态到NoQuarterState   
        System.out.println("退钱返回");
        //把糖果机从有钱状态改成没钱状态
        gumballMachine.setState(gumballMachine.getNoQuarterState());   
    }   
    
    public void turnCrank() {   
        System.out.println("请稍等,一会糖果你就可以拿到了...");   
        int winner = randomWinner.nextInt(10);   
        //决定这个顾客是否赢了   
        if ((winner == 0) && (gumballMachine.getCount() > 1)) {   
            gumballMachine.setState(gumballMachine.getWinnerState());   
        } else {   
            gumballMachine.setState(gumballMachine.getSoldState());   
        }   
    }   
    public void dispense() {    //这是一个对当前状态不恰当的动作   
        System.out.println("请您稍等交易还没有结束。");   
    }   

}

public class NoQuarterState implements State {
	GumballMachineTwo gumballMachine;

	// 通过构造器得到糖果机的引用
	public NoQuarterState(GumballMachineTwo gumballMachine) {
		this.gumballMachine = gumballMachine;
	}

	// 分发物品
	public void dispense() {
		System.out.println("没有钱,不能分发糖果");   
	}

	// 退钱
	public void ejectQuarter() {
		System.out.println("没有钱,不能退钱");

	}

	// 投钱
	public void insertQuarter() {
		// TODO Auto-generated method stub

	}

	// 按纽操作
	public void turnCrank() {
		// TODO Auto-generated method stub

	}

}

public class SoldOutState implements State {
	GumballMachineTwo gumballMachine;

	public SoldOutState(GumballMachineTwo gumballMachine) {
		this.gumballMachine = gumballMachine;
	}

	public void dispense() {
		System.out.println("糖果已经卖没了"); 

	}

	public void ejectQuarter() {
		System.out.println("对不起,糖果已经卖完不能退钱"); 

	}

	public void insertQuarter() {
		System.out.println("糖果已经卖完,不能再向里投钱了");

	}

	public void turnCrank() {
		// TODO Auto-generated method stub

	}

}

public class SoldState implements State{
	GumballMachineTwo gumballMachine;   
    public SoldState(GumballMachineTwo gumballMachine) {   
        this.gumballMachine = gumballMachine;   
    }       
    //以下3个方法对此状态来说都是不恰当的   
    public void insertQuarter() {   
        System.out.println("已向你卖出一个糖果,请稍等,再向里投钱。");   
    }   
    public void ejectQuarter() {   
        System.out.println("对不起,糖果已经卖出不能退钱");   
    }   
    public void turnCrank() {   
        System.out.println("糖果已经卖出,不能再给你了");   
    }   
    //首先让机器发放糖果   
    public void dispense() {   
        gumballMachine.releaseBall();   
        if (gumballMachine.getCount() > 0) {   
            gumballMachine.setState(gumballMachine.getNoQuarterState());   
        } else {   
            System.out.println("Oops, out of gumballs!");   
            gumballMachine.setState(gumballMachine.getSoldOutState());   
        }   
    }   

}

public class WinnerState implements State{
	GumballMachineTwo gumballMachine;   
    //下面都跟SoldState方法一样   
    public WinnerState(GumballMachineTwo gumballMachine) {   
        this.gumballMachine = gumballMachine;   
    }   
    public void insertQuarter() {   
        System.out.println("Please wait, we're already giving you a Gumball");   
    }   
    public void ejectQuarter() {   
        System.out.println("Please wait, we're already giving you a Gumball");   
    }   
    public void turnCrank() {   
        System.out.println("Turning again doesn't get you another gumball!");   
    }   
    //我们在这里发放出2颗糖果,然后进入NoQuarterState或SoldState   
    public void dispense() {   
        System.out.println("YOU'RE A WINNER! You get two gumballs for your quarter");   
        gumballMachine.releaseBall();   
        if (gumballMachine.getCount() == 0) {   
            gumballMachine.setState(gumballMachine.getSoldOutState());   
        } else {   
            gumballMachine.releaseBall();   
            if (gumballMachine.getCount() > 0) {   
                gumballMachine.setState(gumballMachine.getNoQuarterState());   
            } else {   
                System.out.println("Oops, out of gumballs!");   
                gumballMachine.setState(gumballMachine.getSoldOutState());   
            }   
        }   
    }   

}

 

下面是新的糖果类:

public class GumballMachineTwo {
	 //所有的状态都在这里   
    State soldOutState;   
    State noQuarterState;   
    State hasQuarterState;   
    State soldState;   
    
    State winnerState;//十次抽中一次的游戏,新的状态   
    //以及实例变量state   
    State state = soldOutState;   
    int count = 0;//记录糖果数量   
    public GumballMachineTwo(int numberGumballs) {        
        soldOutState = new SoldOutState(this);  //每一种状态也都创建一个状态实例   
        noQuarterState = new NoQuarterState(this);   
        hasQuarterState = new HasQuarterState(this);   
        soldState = new SoldState(this);   
        this.count = numberGumballs;   
        if (numberGumballs > 0) {    //如果超过0颗糖果,状态设为noQuarterState   
            state = noQuarterState;   
        }    
    }   
    //委托给当前状态   
    public void insertQuarter() {   
        state.insertQuarter();   
    }   
    public void ejectQuarter() {   
        state.ejectQuarter();   
    }   
    //dispense()是一个内部动作方法,用户不可以直接要求机器发放糖果   
    public void turnCrank() {   
        state.turnCrank();   
        state.dispense();   
    }   
    //允许其他的对象将机器状态转换到不同的状态   
    void setState(State state) {   
        this.state = state;   
    }   
    //辅助方法释放出糖果,并将count实例变量值减1   
    void releaseBall() {   
        System.out.println("A gumball comes rolling out the slot...");   
        if (count != 0) {   
            count = count - 1;   
        }   
    }   
    int getCount() {   
        return count;   
    }   
    void refill(int count) {   
        this.count = count;   
        state = noQuarterState;   
    }   
    public State getState() {return state;}   
    public State getSoldOutState() {return soldOutState;}   
    public State getNoQuarterState() {return noQuarterState;}   
    public State getHasQuarterState() {return hasQuarterState;}   
    public State getSoldState() {return soldState;}   
    public State getWinnerState() {return winnerState;}   

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值