首页 > 其他 > 详细

设计模式(十)状态模式

时间:2020-05-07 22:20:28      阅读:62      评论:0      收藏:0      [点我收藏+]

状态模式

当我们希望使用一个系统,而不希望知晓系统的操作细节时,可以使用状态模式。

状态模式把系统看作一个自动机,通过各种状态之间的转移来自动运行。状态被视为接口或是抽象类,具体的状态通过实现或者继承的方式来规定状态转移规则(大多数时候使用接口)。用户只需向机器提供输入和请求,机器就能自动实现相应状态的跳转并返回对应的结果。

以糖果机为例。购买糖果的大体流程如下:

  1. 投入硬币
  2. 旋转曲柄
  3. 机器发放糖果
  4. 取出投入的硬币
  5. 要求售罄的机器补充糖果

对应上述五个动作,实际有四个状态:

  • 硬币未投入
  • 硬币已投入
  • 准备发放糖果
  • 糖果已售罄

因此可以定义一个State接口,封装上述五个动作,然后由四个子类分别实现四个状态中对应每个动作的具体操作。

package state;

public interface State {
    public void insertQuarter();
    public void ejectQuarter();
    public void turnCrank();
    public void dispense();
    public void refill();
}
package state;

public class NoQuarterState implements State {
    GumballMachine gumballMachine;

    public NoQuarterState(GumballMachine gumballMachine) {
        this.gumballMachine = gumballMachine;
    }

    @Override
    public void insertQuarter() {
        System.out.println("You inserted a quarter");
        gumballMachine.setState(gumballMachine.getHasQuarterState());
    }

    @Override
    public void ejectQuarter() {
        System.out.println("You haven‘t inserted a quarter");
    }

    @Override
    public void turnCrank() {
        System.out.println("You turned, but there‘s no quarter");
    }

    @Override
    public void dispense() {
        System.out.println("You need tp pay first");
    }

    @Override
    public void refill() {
        System.out.println("Sorry, gumballs are not sold out");
    }
}
package state;

public class GumballMachine {
    State soldOutState;
    State noQuarterState;
    State hasQuarterState;
    State soldState;
    State winnerState;

    State state = soldState;
    int count = 0;

    public GumballMachine(int numberGumballs) {
        soldOutState = new SoldOutState(this);
        noQuarterState = new NoQuarterState(this);
        hasQuarterState = new HasQuarterState(this);
        soldState = new SoldState(this);
        winnerState = new WinnerState(this);
        this.count = numberGumballs;
        if (numberGumballs > 0) {
            state = noQuarterState;
        } else {
            state = soldOutState;
        }
    }

    public void insertQuarter() {
        state.insertQuarter();
    }

    public void ejectQuarter() {
        state.ejectQuarter();
    }

    public void turnCrank() {
        state.turnCrank();
        state.dispense();
    }

    public void refill() {
        state.refill();
    }

    void setState(State state) {
        this.state = state;
    }

    void releaseBall() {
        System.out.println("A gumball comes rolling out the slot...");
        if (count != 0) {
            count--;
        }
    }

    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;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    @Override
    public String toString() {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("Mighty Gumball, Inc.\n");
        stringBuffer.append("Java-enabled Standing Gumball Model #2004\n");
        stringBuffer.append("Inventory: " + getCount() + " gumballs\n");
        return stringBuffer.toString();
    }
}

这里仅以其中一个状态为例,展示状态转移的代码模板。

可以看到,用户只能接触到自动机,而自动机的方法都是调用了其当前状态实例中的方法,因此用户不需要知道机器当前的状态,也可以进行机器目前允许的任何操作,并且能够期待机器返回当前状态与输入对应的正确的结果。

与策略模式的关系

观察代码结构,可以发现状态模式与策略模式的类图是一样的,但两者的目的却截然不同。

策略模式将可以互换的行为封装起来,然后使用委托的方法,由用户决定使用哪一个行为,此时用户清楚地知道每个行为;而状态模式将可以互相转移的状态封装起来,并将行为委托到当前状态,此时用户不知道每个状态的行为,不知道状态之间如何转移,可以轻松地发出请求或提供输入。

设计模式(十)状态模式

原文:https://www.cnblogs.com/aries99c/p/12845635.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!