标签:
作者: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!标签:
原文地址:http://blog.csdn.net/billfeller/article/details/43088569