前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >状态模式

状态模式

作者头像
shysh95
发布2019-12-30 15:16:16
4030
发布2019-12-30 15:16:16
举报
文章被收录于专栏:shysh95shysh95

状态模式允许在内部状态时改变它的行为,在外部看起来好像修改了类。状态模式可以延伸出状态机的概念,状态机据我自己所知在电商系统中用来控制订单状态的流转。关于状态机,大家可以在评论中可以补充一下(状态机的更多应用场景)。

类图
  1. State:该类通常是一个接口或者抽象类,具体视情况而定
  2. ConcreteState:具体的状态类,实现状态的控制
  3. Context:具体需要使用状态的客户段,在其内部通常有各个状态的引用以及一个当前状态的引用,当调用handle方法时,其实将方法的调用转发给给当前状态的handle方法去执行
场景模拟

下面我们模拟一个糖果机的场景,在该场景中我们简化了部分逻辑,毕竟我们只是为了了解学习状态模式,而不是实现一个真正的糖果机系统。下面我们分析一下糖果机的场景。首先我们需要一台糖果机,其次该机器有以下集中状态,待投币状态,已投币状态,售出糖果状态,售空状态。下面我们开始我们的状态分析,首先我们需要一个State接口。

State接口

该接口主要有以下方法,投币、退币、摇动手柄、售出糖果,上面这四个方法会改变糖果机的状态。

代码语言:javascript
复制
public interface State {

    void insertQuarter();

    void ejectQuarter();

    void turnCrank();

    void dispense();
}
NoQuarterState类(待投币状态)

在糖果机在待投币状态下,我们唯一能对糖果机做的操作就是投入硬币,当投入硬币之后我们的糖果机就变成了已投币状态。

代码语言:javascript
复制
public class NoQuarterState implements State {

    private GumballMachine gumballMachine;

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

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

    @Override
    public void ejectQuarter() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void turnCrank() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void dispense() {
        throw new UnsupportedOperationException();
    }
}
HasQuarterState类(已投币状态)

在糖果机有币的状态下我们可以做两种操作,一种选择退出硬币(待投币状态),还有一种就是摇动摇杆去获得糖果(售出糖果状态)。

代码语言:javascript
复制
public class HasQuarterState implements State {

    private GumballMachine gumballMachine;

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

    @Override
    public void insertQuarter() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void ejectQuarter() {
        System.out.println("You eject a quarter!");
        gumballMachine.setCurrentState(gumballMachine.getNoQuarterState());
    }

    @Override
    public void turnCrank() {
        System.out.println("You turn this crank!");
        gumballMachine.setCurrentState(gumballMachine.getSoldState());
    }

    @Override
    public void dispense() {
        throw new UnsupportedOperationException();
    }
}
SoldState(售出糖果状态)

在该状态下,我们需要将糖果给用户,因此我们调用糖果机的售出糖果方法,此时我们需要判断糖果机里是否还有糖果,如果没有糖果了我们就将糖果机置为售空状态(等待工作人员补充糖果后糖果机才可以被再次使用),如果还有糖果我们就将糖果机置为待投币状态,等待下一个用户。

代码语言:javascript
复制
public class SoldState implements State {

    private GumballMachine gumballMachine;

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

    @Override
    public void insertQuarter() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void ejectQuarter() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void turnCrank() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void dispense() {
        gumballMachine.releaseBall();
        if (gumballMachine.getCount() > 0) {
            gumballMachine.setCurrentState(gumballMachine.getNoQuarterState());
        } else {
            gumballMachine.setCurrentState(gumballMachine.getSoldOutState());
        }
    }
}
SoldOutState(售空状态)

在售空状态下我们无法做任何操作。

代码语言:javascript
复制
public class SoldOutState implements State {

    private GumballMachine gumballMachine;

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

    @Override
    public void insertQuarter() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void ejectQuarter() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void turnCrank() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void dispense() {
        throw new UnsupportedOperationException();
    }
}
GumballMachine(糖果机)

有了状态的控制,我们当然要有台糖果机。在糖果机中,我们有四个状态和糖果机当前状态的引用,你会发现我们只是将请求委托给了糖果机的当前状态去实现。

代码语言:javascript
复制
public class GumballMachine {

    private NoQuarterState noQuarterState;

    private HasQuarterState hasQuarterState;

    private SoldState soldState;

    private SoldOutState soldOutState;

    private State currentState;

    private int count;

    public GumballMachine(int count) {
        this.noQuarterState = new NoQuarterState(this);
        this.hasQuarterState = new HasQuarterState(this);
        this.soldState = new SoldState(this);
        this.soldOutState = new SoldOutState(this);
        this.count = count;
        currentState = noQuarterState;
    }

    public GumballMachine(State currentState) {
        this.currentState = currentState;
    }

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

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

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

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

    public void dispense() {
        currentState.dispense();
    }


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

    public NoQuarterState getNoQuarterState() {
        return noQuarterState;
    }

    public HasQuarterState getHasQuarterState() {
        return hasQuarterState;
    }

    public SoldState getSoldState() {
        return soldState;
    }

    public SoldOutState getSoldOutState() {
        return soldOutState;
    }

    public int getCount() {
        return count;
    }
}
测试糖果机

一切准备就绪,是时候测试我们的糖果机了。至于下面的结果大家自己去跑测试吧。

代码语言:javascript
复制
public class GumballMachineTest {

    public static void main(String[] args) {
        GumballMachine gumballMachine = new GumballMachine(2);
        gumballMachine.insertQuarter();
        gumballMachine.turnCrank();

        System.out.println("------------------------------");

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

        System.out.println("------------------------------");

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


        System.out.println("------------------------------");

        gumballMachine.insertQuarter();
        gumballMachine.turnCrank();
    }
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员修炼笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 类图
  • 场景模拟
    • State接口
      • NoQuarterState类(待投币状态)
        • HasQuarterState类(已投币状态)
          • SoldState(售出糖果状态)
            • SoldOutState(售空状态)
              • GumballMachine(糖果机)
                • 测试糖果机
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档