State模式-在自动售货机的应用

State定义
  1. 当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变其类。
  2. 状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂的情况,把状态的判断逻辑转移到表示不同状态
    的一系列类当中,把复杂的判断逻辑简单化。
  3. 将与特定状态的相关行为局部化,并且将不同状态的行为分割开来。什么情况考虑状态模式了,
    当一个对象的行为取决于它的状态
    ,并且它必须在运行的时刻根据状态改变它的行为时,就可以考虑使用状态模式。
例子现在有个自动售货机的代码需要我们来写
  1. 在购买东西过程中包含4个状态,已投币,未投币,售出商品,商品售罄,
  2. 在如下的三个动作(投币,退币,转动手柄)
  3. 当用户调用不同的动作,方法时候。需要判断当前状态得出不同的信息。
  4. 不采用state模式解耦,会有大量代码重复。
例子1
public interface State {

    /**
     * 放钱
     */
    public void insertMoney();

    /**
     * 退钱
     */
    public void backMoney();

    /**
     * 转动
     */
    public void turnCrank();

    /**
     * 出商品
     */
    public void dispense();


}


/**
 * 对象
 */
public class VendingMachine {


    private State noMoneyState;
    private State hasMoneyState;

    private State soldState;
    private State soldOutState;
    private State winnerState;

    private int count = 0;

    /**
     * 当前状态
     */
    private State currentState = noMoneyState;


    public VendingMachine(int count) {
        this.noMoneyState = new NoMoneyState(this);
        this.hasMoneyState = new HasMoneyState(this);
        this.soldState = new SoldState(this);
        this.soldOutState = new SoldOutState(this);

        this.count = count;
        if (count > 0) {
            this.count = count;
            currentState = noMoneyState;
        }

    }


    /**
     * 放钱
     */
    public void insertMoney() {
        currentState.insertMoney();
    }

    /**
     * 退钱
     */
    public void backMoney() {
        currentState.backMoney();
    }

    /**
     * 转动
     */
    public void turnCrank() {
        currentState.turnCrank();
    }

    /**
     * 出商品
     */
    public void dispense() {

    }

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


    public State getNoMoneyState() {
        return noMoneyState;
    }

    public State getHasMoneyState() {
        return hasMoneyState;
    }

    public State getSoldState() {
        return soldState;
    }

    public State getSoldOutState() {
        return soldOutState;
    }

    public State getWinnerState() {
        return winnerState;
    }

    public int getCount() {
        return count;
    }

    public State getCurrentState() {
        return currentState;
    }
}

public   class AbstractState  implements State {
    @Override
    public void insertMoney() {

        System.out.println("请投币");
    }

    @Override
    public void backMoney() {
        System.out.println("你未投币");
    }

    @Override
    public void turnCrank() {
        System.out.println("未投币,就想拿东西");
    }

    @Override
    public void dispense() {
        System.out.println("非法状态");
    }
}

import java.util.Random;

public class HasMoneyState extends AbstractState {

    private VendingMachine machine;
    Random random = new Random();

    public HasMoneyState(VendingMachine machine) {
        this.machine = machine;
    }


    @Override
    public void backMoney() {
        System.out.println("退币成功");
        machine.setState(machine.getNoMoneyState());

    }

    @Override
    public void turnCrank() {
//        System.out.println("未投币,就想拿东西");
        System.out.println("你转动了手柄");

        int winner = random.nextInt(10);
        if (winner == 0 && machine.getCount() > 1) {
            machine.setState(machine.getWinnerState());
        } else {
            machine.setState(machine.getSoldState());
        }

    }
}
/**
 * 没钱状态
 */
public class NoMoneyState extends AbstractState {

    private VendingMachine machine;

    public NoMoneyState(VendingMachine machine) {
        this.machine = machine;
    }

    @Override
    public void insertMoney() {
       System.out.println("系统投币");
        /**
         * 发生投钱动作后,状态发生转换
         */
        machine.setState(machine.getHasMoneyState());
    }

}
/**
 * 售罄状态
 */
public class SoldOutState extends AbstractState {



    private VendingMachine machine;

    public SoldOutState(VendingMachine machine) {
        this.machine = machine;
    }

    @Override
    public void insertMoney() {

    }

    @Override
    public void backMoney() {

    }

    @Override
    public void turnCrank() {
        System.out.println("商品售罄,转动手柄也木有用");


    }

    @Override
    public void dispense() {

    }
}


/**
 * 准备出商品的状态,该状态下,不会任何用户的操作
 */
public class SoldState extends AbstractState {


    private VendingMachine machine;

    public SoldState(VendingMachine machine) {
        this.machine = machine;
    }

    @Override
    public void insertMoney() {

    }

    @Override
    public void backMoney() {

    }

    @Override
    public void turnCrank() {

    }

    @Override
    public void dispense() {
        machine.dispense();
        if (machine.getCount() > 0) {
            machine.setState(machine.getNoMoneyState());
        } else {
            System.out.println("商品已经售罄");
            machine.setState(machine.getSoldOutState());
        }
    }
}


public class ClientTest {

    public static void main(String[] args) {
        VendingMachine machine=new VendingMachine(10);
        machine.insertMoney();

        machine.backMoney();
        System.out.println("----我要中奖----");

        machine.insertMoney();
        machine.turnCrank();
        machine.insertMoney();
        machine.turnCrank();
        machine.insertMoney();
        machine.turnCrank();
        machine.insertMoney();
        machine.turnCrank();
        machine.insertMoney();
        machine.turnCrank();
        machine.insertMoney();
        machine.turnCrank();
        machine.insertMoney();
        machine.turnCrank();

        System.out.println("-------压力测试------");

        machine.insertMoney();
        machine.backMoney();
        machine.backMoney();
        machine.turnCrank();// 无效操作
        machine.turnCrank();// 无效操作
        machine.backMoney();


    }
}

总结
  1. 减少每次调用不同方法动作时候,大量状态判断,而根据当前状态下不同行为直接输出结果。
参考文档

https://blog.csdn.net/lmj623565791/article/details/26350617

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值