标签搜索

状态模式

Pop.Kite
2022-03-13 / 0 评论 / 88 阅读 / 正在检测是否收录...

通过修改类的内部状态来修改类的行为。调用一个对象的方法时会改变对象内部的状态,下次再调用这个对象的方法,会调用新的状态下的对象的方法。

经典的投币机例子,看下类图:(我发现想要写好代码一定要先设计好,要学习画UML图了...)

状态模式.jpg

上面的类图中我们可以找到四个状态:未投币 - 已投币 - 商品售出 - 商品售罄。

四个状态存在于一个环境(Context):投币机

这个投币机有三个动作:投币 - 退币 - 抽奖(这里我加了一个领取的状态)

//状态接口,包含所有动作,用于实现不同的状态
public interface BaseState {
    /**
     * 投币
     */
    void coin();

    /**
     * 退款
     */
    void refund();

    /**
     * 抽奖
     */
    void lottery();

    /**
     * 领取
     */
    void award();
}
//未投币状态
public class NoMoneyState implements BaseState {

    //投币机
    private VehicleMachine vehicleMachine;

    public NoMoneyState(VehicleMachine vehicleMachine) {
        this.vehicleMachine = vehicleMachine;
    }

    @Override
    public void coin() {
        System.out.println("投币成功");
        vehicleMachine.setCurrentState(vehicleMachine.getHasMoneyState());
    }

    @Override
    public void refund() {
        System.out.println("尚未投币,无法退款");
    }

    @Override
    public void lottery() {
        System.out.println("尚未投币,无法抽奖");
    }

    @Override
    public void award() {
        System.out.println("尚未投币,无法领奖");
    }
}
//已投币状态
public class HasMoneyState implements BaseState {

    private VehicleMachine vehicleMachine;

    public HasMoneyState(VehicleMachine vehicleMachine) {
        this.vehicleMachine = vehicleMachine;
    }
    @Override
    public void coin() {
        System.out.println("已经投过币了");
    }

    @Override
    public void refund() {
        System.out.println("已经退款");
        vehicleMachine.setCurrentState(vehicleMachine.getNoMoneyState());
    }

    @Override
    public void lottery() {
        if (vehicleMachine.getGoodCount() <= 0) {
            System.out.println("商品已售罄");
            refund();
        } else {
            System.out.println("正在出货");
            vehicleMachine.setCurrentState(vehicleMachine.getSolingState());
        }
    }

    @Override
    public void award() {
        System.out.println("正在出货");
    }
}
//正在出货状态
public class SolingState implements BaseState {
    private VehicleMachine vehicleMachine;

    public SolingState(VehicleMachine vehicleMachine) {
        this.vehicleMachine = vehicleMachine;
    }

    @Override
    public void coin() {
        System.out.println("正在出货,请稍后");
    }

    @Override
    public void refund() {
        System.out.println("正在出货,请稍后");
    }

    @Override
    public void lottery() {
        System.out.println("正在出货,请稍后");
    }

    @Override
    public void award() {
        System.out.println("商品已领取");
        int count = vehicleMachine.getGoodCount();
        vehicleMachine.setGoodCount(--count);
        vehicleMachine.setCurrentState(vehicleMachine.getNoMoneyState());
    }
}
//售罄状态
public class SoldOutState implements BaseState {

    private VehicleMachine vehicleMachine;

    public SoldOutState(VehicleMachine vehicleMachine) {
        this.vehicleMachine = vehicleMachine;
    }

    @Override
    public void coin() {
        System.out.println("商品已经售罄");
    }

    @Override
    public void refund() {
        System.out.println("商品已经售罄");
    }

    @Override
    public void lottery() {
        System.out.println("商品已经售罄");
    }

    @Override
    public void award() {
        System.out.println("商品已经售罄");
    }
}
//Context:投币机
public class VehicleMachine {

    private NoMoneyState noMoneyState;
    private HasMoneyState hasMoneyState;
    private SolingState solingState;
    private SoldOutState soldOutState;

    private int goodCount = 1;
    private BaseState currentState;

    public VehicleMachine(int goodCount) {
        noMoneyState = new NoMoneyState(this);
        hasMoneyState = new HasMoneyState(this);
        solingState = new SolingState(this);
        soldOutState = new SoldOutState(this);
        this.goodCount = Math.max(goodCount, 1);
        this.currentState = noMoneyState;
    }

    public VehicleMachine coin() {
        currentState.coin();
        return this;
    }

    public VehicleMachine refund() {
        currentState.refund();
        return this;
    }

    public VehicleMachine lottery() {
        currentState.lottery();
        return this;
    }

    public VehicleMachine award() {
        currentState.award();
        return this;
    }

    public void setCurrentState(BaseState state){
        this.currentState = state;
    }

    public NoMoneyState getNoMoneyState() {
        return noMoneyState;
    }

    public HasMoneyState getHasMoneyState() {
        return hasMoneyState;
    }

    public SolingState getSolingState() {
        return solingState;
    }

    public SoldOutState getSoldOutState() {
        return soldOutState;
    }

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

    public int getGoodCount() {
        return goodCount;
    }

    public BaseState getCurrentState() {
        return currentState;
    }
}

运行示例

//代码运行示例
VehicleMachine vehicleMachine = new VehicleMachine(1);
vehicleMachine.coin().lottery().refund().award();
vehicleMachine.refund();
vehicleMachine.coin().refund().lottery().refund().award();

投币成功
正在出货
正在出货,请稍后
商品已领取
尚未投币,无法退款
投币成功
已经退款
尚未投币,无法抽奖
尚未投币,无法退款
尚未投币,无法领奖
0

评论 (0)

取消