首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >PHP状态机框架

PHP状态机框架
EN

Stack Overflow用户
提问于 2010-11-25 13:32:07
回答 8查看 18.2K关注 0票数 20

我怀疑有没有像https://github.com/pluginaweek/state_machine这样的状态机框架。

我不得不定义许多if-else逻辑子句,我希望通过定义以下内容来使其更有趣:

转换后transition

  • State所需的
  1. 条件

然后,可以重用它来检查条件是否匹配,例如

代码语言:javascript
复制
$customer->transition('platinum');

我希望这一行代码能够隐式地检查客户是否可以转换。或通过以下方式显式检查:

代码语言:javascript
复制
$customer->canTransitTo('platinum');

提前谢谢你,努姆兹

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2010-11-25 16:59:45

我不知道这样的框架(这并不意味着它不存在)。但是,虽然不像链接框架那样具有丰富的功能,但State pattern实现起来相当简单。考虑下面这个简单的实现:

代码语言:javascript
复制
interface EngineState
{
    public function startEngine();
    public function moveForward();
}

class EngineTurnedOffState implements EngineState
{
    public function startEngine()
    {
        echo "Started Engine\n";
        return new EngineTurnedOnState;
    }
    public function moveForward()
    {
        throw new LogicException('Have to start engine first');
    }
}

class EngineTurnedOnState implements EngineState
{
    public function startEngine()
    {
        throw new LogicException('Engine already started');
    }
    public function moveForward()
    {
        echo "Moved Car forward";
        return $this;
    }
}

定义状态后,您只需将它们应用于主对象:

代码语言:javascript
复制
class Car implements EngineState
{
    protected $state;
    public function __construct()
    {
        $this->state = new EngineTurnedOffState;
    }
    public function startEngine()
    {
        $this->state = $this->state->startEngine();
    }
    public function moveForward()
    {
        $this->state = $this->state->moveForward();
    }
}

然后你就可以

代码语言:javascript
复制
$car = new Car;
try {
    $car->moveForward(); // throws Exception
} catch(LogicException $e) {
    echo $e->getMessage();
}

$car = new Car;
$car->startEngine();
$car->moveForward();

对于减少过大的if/else语句,这应该足够了。请注意,在每次转换时返回一个新的状态实例有点低效。正如我所说的,这是一个天真的实现来说明这一点。

票数 42
EN

Stack Overflow用户

发布于 2010-11-25 17:04:19

票数 10
EN

Stack Overflow用户

发布于 2012-11-19 05:13:05

我一直在开发一个简单的PHP有限状态机库,有点类似于rails的state_machine。代码在这里:https://github.com/chriswoodford/techne/tree/v0.1

一个汽车例子,类似于上面选择的答案,看起来像这样:

初始化

代码语言:javascript
复制
  $machine = new StateMachine\FiniteStateMachine();
  $machine->addEvent('start', array('parked' => 'idling'));
  $machine->addEvent('drive', array('idling' => 'driving'));
  $machine->addEvent('stop', array('driving' => 'idling'));
  $machine->addEvent('park', array('idling' => 'parked'));
  $machine->setInitialState('parked');

用法

代码语言:javascript
复制
  $machine->start();
  echo $machine->getCurrentStatus();
  // prints "idling"     

  $machine->drive();
  echo $machine->getCurrentStatus();
  // prints "driving"

  $machine->stop();
  echo $machine->getCurrentStatus();
  // prints "idling"

  $machine->park();
  echo $machine->getCurrentStatus();
  // prints "parked"

它缺少一个显式定义的接口,因为它使用__call()魔术方法来接受消息,但这可以通过adapter轻松解决。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4274031

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档