potfur / statemachine
状态机
2.0.0
2015-08-02 09:25 UTC
Requires
- php: >=5.4
Requires (Dev)
- phpmd/phpmd: ~2.2
- phpunit/phpunit: ~4.6
- squizlabs/php_codesniffer: ~2.3
This package is not auto-updated.
Last update: 2024-09-14 17:05:23 UTC
README
状态机是实现 状态模式 的实现,也可以被视为 非确定性有限自动机。换句话说——机器会根据执行的 命令 结果对事件做出反应,并将 上下文 从一个状态移动到另一个状态。
状态机可以用来描述订单与支付处理、新闻通讯订阅过程、客户注册等任何非简单过程。
流程
状态机遵循由 状态 和 事件 定义的流程,状态 是 上下文 所采取的,事件 激活了它们之间的转换。
每个 事件 可以定义两个转换 成功的 和 错误的。此外,每个 事件 都可以有一个可调用的命令,该命令在转换之前执行。由它返回的值将决定选择哪个转换。
当 命令 返回 真值
时,状态机将遵循 成功的 转换,任何 假值
都将是 错误的 转换。如果 事件 没有定义 命令,状态机将遵循 成功的 转换。
每个 状态 都可以有一个特殊的事件 StateMachine::ON_STATE_WAS_SET
,一旦 上下文 进入状态,它就会触发。
模式
流程是由模式构建的。状态机附带 ArrayFactory
,它可以从平面数组创建 Process
实例。
$commandResults = [ true, // from new to pending false, // from pending to error (onStateWasSet) true, // from error to pending (onStateWasSet) true, // from pending to done (onStateWasSet) ]; $command = function () use (&$commandResults) { if (!count($commandResults)) { throw new \InvalidArgumentException('Out of results'); } return array_shift($commandResults); }; $schema = [ 'name' => 'testSchema', 'initialState' => 'new', 'states' => [ [ 'name' => 'new', 'events' => [ [ 'name' => 'goPending', 'targetState' => 'pending', 'errorState' => 'error', 'command' => $command, ] ], ], [ 'name' => 'pending', 'events' => [ [ 'name' => StateMachine::ON_STATE_WAS_SET, 'targetState' => 'done', 'errorState' => 'error', 'command' => $command ] ], ], [ 'name' => 'error', 'events' => [ [ 'name' => StateMachine::ON_STATE_WAS_SET, 'targetState' => 'pending', 'errorState' => 'error', 'command' => $command ] ], ], [ 'name' => 'done', 'events' => [], ] ] ]; $process = (new ArrayFactory($schema))->getProcess();
有效载荷和触发事件
要从一种状态转换到另一种状态,需要触发一个事件。当发生这种情况时,状态机会将提供的 上下文 包装为有效载荷传递给 命令,执行它并遵循结果的转换。
$payload = PayloadEnvelope::wrap('context'); $machine = new StateMachine($process); $history = $machine->triggerEvent('goPending', $payload);
PayloadEnvelope
是 Payload
的实现——一个简单的包装器,用于持有 上下文。它可以是一切,简单的值、数组、对象等。`::triggerEvent` 方法返回转换历史,即上下文通过的所有状态的列表。