行为型设计模式(五)状态模式【超级玛丽要变身】

状态模式一般用来实现状态机,而状态机常用在游戏、工作流引擎等系统开发中。不过,状态机的实现方式有多种,除了状态模式,比较常用的还有分支逻辑法和查表法。今天,详细讲讲这几种实现方式,并且对比一下它们的优劣和应用场景。

一、状态机

有限状态机,英文翻译是 Finite State Machine,缩写为 FSM,简称为状态机。状态机有 3 个组成部分:状态(State)、事件(Event)、动作(Action)。其中,事件也称为转移条件(Transition Condition)。事件触发状态的转移及动作的执行。不过,动作不是必须的,也可能只转移状态,不执行任何动作。

超级马里奥游戏中,马里奥可以变身为多种形态,比如小马里奥(Small Mario)、超级马里奥(Super Mario)、火焰马里奥(Fire Mario)、斗篷马里奥(Cape Mario)等等。在不同的游戏情节下,各个形态会互相转化,并相应的增减积分。比如,初始形态是小马里奥,吃了蘑菇之后就会变成超级马里奥,并且增加 100 积分。

实际上,马里奥形态的转变就是一个状态机。其中,马里奥的不同形态就是状态机中的“状态”,游戏情节(比如吃了蘑菇)就是状态机中的“事件”,加减积分就是状态机中的“动作”。比如,吃蘑菇这个事件,会触发状态的转移:从小马里奥转移到超级马里奥,以及触发动作的执行(增加 100 积分)。

如何将上面的状态转移图翻译成代码呢?
先给出整体实现功能的一个框架代码


public enum State {
   
  SMALL(0),
  SUPER(1),
  FIRE(2),
  CAPE(3);

  private int value;

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

  public int getValue() {
   
    return this.value;
  }
}

public class MarioStateMachine {
   
  private int score;
  private State currentState;

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

  public void obtainMushRoom() {
   
    //TODO
  }

  public void obtainCape() {
   
    //TODO
  }

  public void obtainFireFlower() {
   
    //TODO
  }

  public void meetMonster() {
   
    //TODO
  }

  public int getScore() {
   
    return this.score;
  }

  public State getCurrentState() {
   
    return this.currentState;
  }
}

public class ApplicationDemo {
   
  public static void main(String[] args) {
   
    MarioStateMachine mario = new MarioStateMachine();
    mario.obtainMushRoom();
    int score = mario.getScore();
    State state = mario.getCurrentState();
    System.out.println("mario score: " + score + "; state: " + state);
  }
}

二、解决状态机的几种思路

2.1 分支逻辑法

参照状态转移图,将每一个状态转移,原模原样地直译成代码。这样编写的代码会包含大量的 if-else 或 switch-case 分支判断逻辑,甚至是嵌套的分支判断逻辑,所以,我把这种方法暂且命名为分支逻辑法。
补全代码如下所示


public class MarioStateMachine {
   
  private int score;
  private State currentState;

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

  public void obtainMushRoom() {
   
    if (currentState.equals(State.SMALL)) {
   
      this.currentState = State.SUPER;
      this.score += 100;
    }
  }

  public void obtainCape() {
   
    if (currentState.equals(State.SMALL) || currentState.equals(State.SUPER) ) {
   
      this.currentState = State.CAPE;
      this.score += 200;
    }
  }

  public void ob
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值