状态模式

状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

示例—糖果机的实现

糖果机的主要流程是:开始没有硬币投入的状态,用户在投入硬币后,糖果机转为已投入硬币状态。这时,用户可以选择旋转把手或者退钱。选择旋转把手后,状态变更为已售出。糖果掉落后,如果还有糖果,状态变更为没有硬币;如果没有糖果了,状态变更为售光。选择退钱后,硬币退回,状态变更为没有硬币。还有一个抽奖机制,把手旋转的时候有10%的几率掉落2个糖果。

UML图表示

状态模式-糖果机

代码演示

状态接口

package State;

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

无硬币状态类

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 need to pay first");
    }

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

    @Override
    public String toString() {
        return this.getClass().getName();
    }
}

有硬币状态类

package State;

import java.util.Random;

public class HasQuarterState implements State {

    GumballMachine gumballMachine;
    Random randomWinner = new Random(System.currentTimeMillis());

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

    @Override
    public void insertQuarter() {
        System.out.println("You can't insert another quarter");
    }

    @Override
    public void ejectQuarter() {
        System.out.println("Quarter returned");
        gumballMachine.setState(gumballMachine.getNoQuarterState());
    }

    @Override
    public void turnCrank() {
        System.out.println("You turned...");
        int winner = randomWinner.nextInt(10);
        if ((winner == 0) && (gumballMachine.getCount() > 1)){
            gumballMachine.setState(gumballMachine.getWinnerState());
        }
        else{
            gumballMachine.setState(gumballMachine.getSoldState());
        }
    }

    @Override
    public void dispense() {
        System.out.println("No gumball dispensed");
    }

    @Override
    public String toString() {
        return this.getClass().getName();
    }
}

售出状态类

package State;

public class SoldState implements State {

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

    @Override
    public void insertQuarter() {
        System.out.println("Please wait,we've already giving you a gumball");
    }

    @Override
    public void ejectQuarter() {
        System.out.println("Sorry, you already turned the crank");
    }

    @Override
    public void turnCrank() {
        System.out.println("Turning twice doesn't get you another gumball!");
    }

    @Override
    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());
        }

    }

    @Override
    public String toString() {
        return this.getClass().getName();
    }
}

售罄状态类

package State;

public class SoldOutState implements State {

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

    @Override
    public void insertQuarter() {
        System.out.println("You can't insert a quarter,the machine is sold out");
    }

    @Override
    public void ejectQuarter() {
        System.out.println("You can't eject,you haven't inserted a quarter yet");
    }

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

    @Override
    public void dispense() {
        System.out.println("No gumball dispensed");
    }
    @Override
    public String toString() {
        return this.getClass().getName();
    }
}

获奖状态类

package State;

public class WinnerState implements State {

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

    @Override
    public void insertQuarter() {
        System.out.println("You can't insert a quarter");
    }

    @Override
    public void ejectQuarter() {
        System.out.println("You can't eject");
    }

    @Override
    public void turnCrank() {
        System.out.println("Turning twice doesn't get you third gumball!");
    }

    @Override
    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());
            }
        }
    }

    @Override
    public String toString() {
        return this.getClass().getName();
    }
}

糖果机类

package State;

public class GumballMachine {

    State soldOutState;
    State noQuarterState;
    State hasQuarterState;
    State soldState;
    State winnerState;

    private State state = soldOutState;
    private 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;
        }
    }

    @Override
    public String toString() {
        return "GumballMachine has " + count + " gumballs now, current state is " + state.toString();
    }

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

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

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


    public State getState() {
        return state;
    }

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

    public State getHasQuarterState(){
        return hasQuarterState;
    }

    public State getNoQuarterState(){
        return noQuarterState;
    }

    public State getSoldState(){
        return soldState;
    }

    public State getSoldOutState(){
        return soldOutState;
    }

    public State getWinnerState() {
        return winnerState;
    }

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

    public int getCount() {
        return count;
    }

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

测试代码

package State;

public class GumballMachineTestDrive {
    public static void main(String[] args) {
        GumballMachine gumballMachine = new GumballMachine(5);
        System.out.println(gumballMachine);

        gumballMachine.insertQuarter();
        gumballMachine.turnCrank();

        System.out.println(gumballMachine);

        gumballMachine.insertQuarter();
        gumballMachine.turnCrank();
        gumballMachine.insertQuarter();
        gumballMachine.turnCrank();

        System.out.println(gumballMachine);

    }
}

测试结果

GumballMachine has 5 gumballs now, current state is State.NoQuarterState
You inserted a quarter
You turned...
YOU'RE A WINNER! You get two gumballs for your quarter
A gumball comes rolling out the slot...
A gumball comes rolling out the slot...
GumballMachine has 3 gumballs now, current state is State.NoQuarterState
You inserted a quarter
You turned...
A gumball comes rolling out the slot...
You inserted a quarter
You turned...
A gumball comes rolling out the slot...
GumballMachine has 1 gumballs now, current state is State.NoQuarterState
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 标签: python 设计模式 引子 状态模式确实很好玩,我是说书上的例子确实很好玩,我对着电脑玩了好长时间,但是...
    plectrum阅读 2,861评论 0 7
  • 今天我们来做一个糖果机吧,用户只需要投入25美分,就可以购买糖果了,具体的构造如下图所示: 每个圆圈都表示一种状态...
    西木柚子阅读 1,092评论 1 11
  • 定义:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。状态模式主要解决的是当控制一个对象状...
    yangzai阅读 333评论 0 0
  • 3.4 模拟工作流## 做企业应用的朋友,大多数都接触过工作流,至少处理过业务流程。当然对于工作流,复杂的应用可能...
    七寸知架构阅读 2,121评论 1 53
  • 1 场景问题# 1.1 实现在线投票## 考虑一个在线投票的应用,要实现控制同一个用户只能投一票,如果一个用户反复...
    七寸知架构阅读 1,990评论 7 53