有限状态机的实现

作者:zhanhailiang 日期:2015-01-24

什么是有限状态机

一个有限状态机是一个设备,或是一个设备模型,具有有限数量的状态,它可以在任何给定的时间根据输入进行操作,使其从一个状态变换到另一个状态,或者是促使一个输出或者一种行为的发生。一个有限状态机在任何瞬间只能处在一个状态。

即有限状态机背后的概念是要把一个对象的行为分解成为易于处理的“块”或状态。典型的例子,墙上的灯是一个非常简单的有限状态机,它有两种状态:开或关。状态之间的变换是通过你手指的输入产生的。向上按开关,产生从开到关的状态变换,向下按开关,产生从开到关的状态变换。

关闭状态:没有相应的输出或行动(除非考虑灯泡不亮也是一种行动);
开启状态:允许电流流过开关并通过灯泡丝点亮你的房间。

状态机的实现

使用switch语句来表达状态的代码如下:

switch ($state) {
    case STATE_RUNAWAY : // 逃跑状态
        // 躲避敌人
        // 若安全,进入巡逻状态
        break;
    case STATE_PATROL :  // 巡逻状态
        // 巡逻
        // 若遇到比自己强的敌人,进入逃跑状态
        // 若遇到比自己弱的敌人,进入攻击状态
        break;
    case STATE_ATTACK : // 攻击状态
        // 若攻击比自己强的敌人,进入逃跑状态
        // 否则取其首级
        break;
    // etc...
}

使用switch实现的有限状态机,随着更多的状态和条件的加入,将导致代码流程象意大利面条一样难以理解并且产生调试恶梦。

接下来使用状态变换表表示以上示例状态变换关系

当前状态条件状态变换
逃跑安全巡逻
攻击比故人弱逃跑
巡逻受到威胁并比敌人强攻击
巡逻受到威胁并比敌人弱逃跑

接下来使用状态设计模式实现以上的有限状态机。它提供了一种优雅的方式来实现状态驱动行为。

请见:

<?php
// vim: set expandtab cindent tabstop=4 shiftwidth=4 fdm=marker:

/**
 * @file     RunnerTest.php
 * @version  1.0
 * @author   wade
 * @date     2015-01-24 19:57:53
 */

/**
 * 有限状态机实现demo
 */

interface State {
    public function execute(Troll $troll);
}

class Troll {
    private $uid;
    private $_curState = NULL;

    public function __construct($uid) {
        $this->uid = $uid;
    }

    public function Update() {
        if ($this->_curState instanceof State) {
            $this->_curState->execute($this);
        }
    }

    public function changeState(State $state) {
        $this->_curState = $state;
    }

    public function isPatrolState() {
        return TRUE;
    }

    public function patrol() {
        echo sprintf("%d is patroling!\n", $this->uid);
    }

    public function isAttackState() {
        return TRUE;
    }

    public function attack() {
        echo sprintf("%d is attacking!\n", $this->uid);
    }

    public function isRunawayState() {
        return TRUE;
    }

    public function runaway() {
        echo sprintf("%d is running away!\n", $this->uid);
    }
}

class PatrolState implements State {
    public function execute(Troll $troll) {
        if ($troll->isPatrolState()) {
            $troll->patrol();
        } else {
            // todo
        }
    }
}

class AttackState implements State {
    public function execute(Troll $troll) {
        if ($troll->isAttackState()) {
            $troll->attack();
        } else {
            // todo
        }
    }
}

class RunawayState implements State {
    public function execute(Troll $troll) {
        if ($troll->isRunawayState()) {
            $troll->runaway();
        } else {
            // todo
        }
    }
}

$uid = 10001;
$troll = new Troll($uid);

$PatrolState = new PatrolState();
$troll->changeState($PatrolState);
$troll->Update();

$AttackState = new AttackState();
$troll->changeState($AttackState);
$troll->Update();

$RunawayState = new RunawayState();
$troll->changeState($RunawayState);
$troll->Update();

查看输出如下:

[root@~/wade/git/billfeller.github.io/code]# /usr/local/php/bin/php RunnerTest.php 
10001 is patroling!
10001 is attacking!
10001 is running away!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值