zinovyev/php-fsm

PHP 有限状态机

v0.6.5 2014-05-20 11:08 UTC

This package is not auto-updated.

Last update: 2024-09-20 21:57:46 UTC


README

有限状态机允许您创建一个包含不同状态及其之间转换的对象,该对象可以根据当前状态改变其行为。

安装

要安装 FSM 机器,请使用 Composer。只需将以下内容添加到您的 composer.json 文件中

    "require": {
        "zinovyev/php-fsm": "0.6.5"
    }

创建状态机步骤

  • 创建状态类并定义状态
class StateA extends State
{
    public function foo($name)
    {
        printf("Hello, %s!", $name);
    }
}
  • 创建一个新的 FSM\Client 实例(状态机)。
  • 将您的状态绑定到客户端实例,应用事务并设置初始状态
class StateMachine extends Client
{
    public function __construct()
    {
        parent::__construct();
        
        /* ... */
        
        $this
            ->addState($stateA)
            /* ... */
            ->createTransition('fourth', 'stateA', 'stateB')
            /* ... */

$stateMachine = new Client;
$stateMachine
    ->addState($stateA)
    ->addState($stateB)
    ->createTransition('fourth', 'stateA', 'stateB')
;
  • 如果您想存储当前状态和参数并在稍后恢复它们,请使用 Memento
$memento = $stateMachine->createMemento();

并恢复

$stateMachine = new StateMachine();
$stateMachine->applyMemento($memento);
  • 这就完成了!您简单的状态机现在已配置并准备好使用!

示例代码

<?php
require_once('vendor/autoload.php');

use FSM\Client;
use FSM\State\State;
use FSM\State\StateInterface;

/**
 * StateA class
 */
class StateA extends State
{
    public function foo($f)
    {
        return $f;
    }
}

/**
 * StateB class
 */
class StateB extends State
{
    public function bar($b)
    {
        return $b * 2;
    }
}

/**
 * StateC class
 */
class StateC extends State
{
    public function fooBar($fb)
    {
        return strrev($fb);
    }
    
    public function shuffle(array $array) {
        shuffle($array);
        return $array;
    }
}


/**
 * StateMachine example class
 */
class StateMachine extends Client
{
    public function __construct()
    {
        parent::__construct();
        
        // Create StateA initial type instance of class StateA
        $stateA = new StateA();
        $stateA->setName('stateA');
        $stateA->setType(StateInterface::TYPE_INITIAL);
        
        // Create StateB finite type instance of class StateB
        $stateB = new StateB();
        $stateB->setName('stateB');
        $stateB->setType(StateInterface::TYPE_FINITE);
        
        // Create StateC regular type instance of class StateC
        $stateC = new StateC();
        $stateC->setName('stateC');
        $stateC->setType(StateInterface::TYPE_REGULAR);
        
        // Create StateD regular type instance of class StateB
        $stateD = new StateB();
        $stateD->setName('stateD');
        $stateD->setType(StateInterface::TYPE_REGULAR);        
        
        // Attach states and transitions
        $this
            ->addState($stateA)
            ->addState($stateB)
            ->addState($stateC)
            ->addState($stateD)
            ->setInitialState($stateA)
            ->createTransition('initial', 'stateA', 'stateA')
            ->createTransition('second', 'stateA', 'stateC')
            ->createTransition('secondAlternative', 'stateA', 'stateD')
            ->createTransition('third', 'stateC', 'stateD')
            ->createTransition('thirdAlternative', 'stateD', 'stateC')
            ->createTransition('fourth', 'stateD', 'stateB')
            ->createTransition('fourthAlternative', 'stateC', 'stateB')
            ->createTransition('shortWay', 'stateA', 'stateB')
        ;
        
    }
}


// Create new StateMachine instance
$stateMachine = new StateMachine();
$stateMachine->foo = 'bar'; // Add public property


// Test StateA state
printf("%d) State machine is at state: '%s'. Test function call result is: '%s'\n", 1,
    $stateMachine->getCurrentState()->getName(),            // Get State Name
    $stateMachine->callAction('foo', $properties = [100])   // Call State function
);

// Accept transition "initial"
$stateMachine->acceptTransitionByName('initial');
printf("%d) State machine is at SAME state: '%s'. Test function call result: '%s'\n", 2,
    $stateMachine->getCurrentState()->getName(),            // Get State Name
    $stateMachine->callAction('foo', $properties = [200])   // Call State function
);

// Accept transition "second"
$stateMachine->acceptTransitionByName('second');
printf("%d) State machine is at state: '%s'. Test function call result: '%s'\n", 3,
    $stateMachine->getCurrentState()->getName(),            // Get State Name
    $stateMachine->fooBar('foo bar')                        // Call State function
);

// Create a memento (snapshot) of the current state
$memento = $stateMachine->createMemento();

// Unset StateMachine
$stateMachine = null;
unset($stateMachine);

// Restore StateMachine from a snapshot (Memento)
$stateMachine = new StateMachine();
$stateMachine->applyMemento($memento);

printf("=*= Check property value after restore: \$foo='%s' =*=\n", $stateMachine->foo);

// Accept transition "third"
$stateMachine->acceptTransitionByName('third');
printf("%d) State machine is at state '%s'. Test function call result: '%s'\n", 4,
    $stateMachine->getCurrentState()->getName(),    // Get State Name
    $stateMachine->bar(1)                           // Call State function
);

// Accept transition "fourth"
$stateMachine->acceptTransitionByName('fourth');
printf("%d) State machine is at state '%s'. Test function call result: '%s'\n", 5,
    $stateMachine->getCurrentState()->getName(),    // Get State Name
    $stateMachine->bar(2)                           // Call State function
);

示例代码执行结果

如果您在控制台中运行此代码,您将看到以下输出:

1) State machine is at state: 'stateA'. Test function call result is: '100'
2) State machine is at SAME state: 'stateA'. Test function call result: '200'
3) State machine is at state: 'stateC'. Test function call result: 'rab oof'
=*= Check property value after restore: $foo='bar' =*=
4) State machine is at state 'stateD'. Test function call result: '2'
5) State machine is at state 'stateB'. Test function call result: '4'