16-状态模式

 


16-状态模式

1.分支判断法实现状态机

public enum State {

    SMALL(0),
    SUPER(1),
    FIRE(2),
    CAPE(3);

    private final int value;
    private State(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

public class MarioStateMachine {

    private int score;
    private State currentState;

    public MarioStateMachine() {
        this.score = 0;
        this.currentState = State.SMALL;
    }

    // 吃了蘑菇,分数加100,状态变为SUPER。
    public void obtainMushRoom() {
        if (this.currentState.equals(State.SMALL)) {
            this.currentState = State.SUPER;
            this.score += 100;
        }
    }

    // 获得斗篷,分数加200,状态变为CAPE。
    public void obtainCape() {
        if (this.currentState.equals(State.SMALL) || this.currentState.equals(State.SUPER)) {
            this.currentState = State.CAPE;
            this.score += 200;
        }
    }

    // 获得火焰,分数加300,状态变为FIRE。
    public void obtainFireFlower() {
        if (this.currentState.equals(State.SMALL) || this.currentState.equals(State.SUPER)) {
            this.currentState = State.FIRE;
            this.score += 300;
        }
    }

    // 遇到怪物。
    public void meetMonster() {
        if (this.currentState.equals(State.SUPER)) {
            this.currentState = State.SMALL;
            this.score -= 100;
            return;
        }

        if (this.currentState.equals(State.CAPE)) {
            this.currentState = State.SMALL;
            this.score -= 200;
            return;
        }

        if (this.currentState.equals(State.FIRE)) {
            this.currentState = State.SMALL;
            this.score -= 300;
        }
    }

    public int getScore() {
        return score;
    }

    public State getCurrentState() {
        return currentState;
    }
}

2.查表法实现状态机

public enum State {

    SMALL(0),
    SUPER(1),
    FIRE(2),
    CAPE(3);

    private final int value;
    private State(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

public enum Event {

    OBTAIN_MUSHROOM(0),
    OBTAIN_CAPE(1),
    OBTAIN_FIRE(2),
    MEET_MONSTER(3);

    private final int value;

    private Event(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

public class MarioStateMachine {

    private int score;
    private State currentState;
    /*
            obtainMushRoom(吃蘑菇) obtainCape(遇到斗篷)    obtainFireFlower(遇到火)   meetMonster(遇到怪物)
    SMALL       SUPER                   CAPE                    FIRE                        SMALL
    SUPER       SUPER                   CAPE                    FIRE                        SMALL
    CAPE        CAPE                    CAPE                    CAPE                        SMALL
    FIRE        FIRE                    FIRE                    FIRE                        SMALL
     */
    private static final State[][] transitionTable = {
            {State.SUPER, State.CAPE, State.FIRE, State.SMALL},
            {State.SUPER, State.CAPE, State.FIRE, State.SMALL},
            {State.CAPE, State.CAPE, State.CAPE, State.SMALL},
            {State.FIRE, State.FIRE, State.FIRE, State.SMALL},
    };
    private static final int[][] actionTable = {
            {+100, +200, +300, +0},
            {+0, +200, +300, -100},
            {+0, +0, +0, -200},
            {+0, +0, +0, -300},
    };

    public MarioStateMachine() {
        this.score = 0;
        this.currentState = State.SMALL;
    }

    // 吃了蘑菇,分数加100,状态变为SUPER。
    public void obtainMushRoom() {
        executeEvent(Event.OBTAIN_MUSHROOM);
    }

    // 获得斗篷,分数加200,状态变为CAPE。
    public void obtainCape() {
        executeEvent(Event.OBTAIN_CAPE);
    }

    // 获得火焰,分数加300,状态变为FIRE。
    public void obtainFireFlower() {
        executeEvent(Event.OBTAIN_FIRE);
    }

    // 遇到怪物。
    public void meetMonster() {
        executeEvent(Event.MEET_MONSTER);
    }

    private void executeEvent(Event event) {
        int stateValue = currentState.getValue();
        int eventValue = event.getValue();
        this.currentState = transitionTable[stateValue][eventValue];
        this.score += actionTable[stateValue][eventValue];
    }

    public int getScore() {
        return score;
    }

    public State getCurrentState() {
        return currentState;
    }
}

3.状态模式实现状态机

public enum State {

    SMALL(0),
    SUPER(1),
    FIRE(2),
    CAPE(3);

    private final int value;
    private State(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

// 所有状态类接口
public interface IMario {

    State getName();
    void obtainMushRoom();
    void obtainCape();
    void obtainFireFlower();
    void obtainMonster();
}

public class SmallMario implements IMario {

    private final MarioStateMachine stateMachine;
    public SmallMario(MarioStateMachine stateMachine) {
        this.stateMachine = stateMachine;
    }

    @Override
    public State getName() {
        return State.SMALL;
    }

    @Override
    public void obtainMushRoom() {
        stateMachine.setCurrentState(new SuperMario());
        stateMachine.setScore(stateMachine.getScore() + 100);
    }

    @Override
    public void obtainCape() {
        stateMachine.setCurrentState(new CapeMario());
        stateMachine.setScore(stateMachine.getScore() + 200);
    }

    @Override
    public void obtainFireFlower() {
        stateMachine.setCurrentState(new FireMario());
        stateMachine.setScore(stateMachine.getScore() + 300);
    }

    @Override
    public void obtainMonster() {
        // 游戏结束
    }
}

// 省略SuperMario、CapeMario和FireMario

public class MarioStateMachine {

    private int score;
    private IMario currentState;

    public MarioStateMachine() {
        this.score = 0;
        this.currentState = new SmallMario(this);
    }

    // 吃了蘑菇,分数加100,状态变为SuperMario。
    public void obtainMushRoom() {
        this.currentState.obtainMushRoom();
    }

    // 获得斗篷,分数加200,状态变为CapeMario。
    public void obtainCape() {
        this.currentState.obtainCape();
    }

    // 获得火焰,分数加300,状态变为FireMario。
    public void obtainFireFlower() {
        this.currentState.obtainFireFlower();
    }

    // 遇到怪物。
    public void meetMonster() {
        this.currentState.obtainMonster();
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public IMario getCurrentState() {
        return currentState;
    }

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

4.状态模式总结

  1. 状态机的实现有三种方式:分支判断法、查表法和状态模式。
    1. 分支法适用于简单的状态机,对于复杂的状态机使用分支法会出现大量冗余的代码。
    2. 查表法适用于复制的状态机。
    3. 状态模式适用于每种状态的处理包含复制的逻辑,并且有较少的状态,如果状态较多,这产生较多的状态类。
  2. 对于游戏类应用,包含的状态比较多,状态模式会引入非常多的状态类,将导致代码比较难维护,因此可以优先使用查表法;对于电商下单、外卖下单类应用,包含的状态较少,但是状态触发执行的业务逻辑可能比较复杂,因此可以优先使用状态模式。
posted @   行稳致远方  阅读(26)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示