简介
跟状态机密切相关。有限状态机 FSM 包含 状态、事件、动作三个元素。
当发生一个事件时,引发老状态变成新状态,并执行一个动作。
状态和行为间一般是有限制的,如某些行为只能再某些状态下进行,某些状态只能触发某些行为。
简单的状态间转换可使用 if else。
更有条理的可以用查表法:二维表中纵向是状态,横向是事件,value 则是新状态和动作。做成二维数组配置,事件发生时结合当前状态,组成[老状态][事件]索引去查二维表,得出 value 是新状态和动作,如果没有 value 则不变换
再复杂一些之后,可使用状态模式。
角色
类图
如图,Context/Machine 中可以 changeState 来改变当前的状态,其中 doThis 和 doThat 签名与 State 一致,这样看起来就像改变状态的同时,改变了 Context 的行为。
类图
代码
class Context
{
private $state;
public function __construct(State $state)
{
$this->transitionTo($state);
}
public function transitionTo(State $state): void
{
echo "Context: Transition to " . get_class($state) . ".\n";
$this->state = $state;
$this->state->setContext($this);
}
public function request1(): void
{
$this->state->handle1();
}
public function request2(): void
{
$this->state->handle2();
}
}
abstract class State
{
protected $context;
public function setContext(Context $context)
{
$this->context = $context;
}
abstract public function handle1(): void;
abstract public function handle2(): void;
}
class ConcreteStateA extends State
{
public function handle1(): void
{
echo "ConcreteStateA handles request1.\n";
echo "ConcreteStateA wants to change the state of the context.\n";
$this->context->transitionTo(new ConcreteStateB());
}
public function handle2(): void
{
echo "ConcreteStateA handles request2.\n";
}
}
class ConcreteStateB extends State
{
public function handle1(): void
{
echo "ConcreteStateB handles request1.\n";
}
public function handle2(): void
{
echo "ConcreteStateB handles request2.\n";
echo "ConcreteStateB wants to change the state of the context.\n";
$this->context->transitionTo(new ConcreteStateA());
}
}
$context = new Context(new ConcreteStateA());
$context->request1();
$context->request2();
复制代码
output:
Context: Transition to ConcreteStateA.
ConcreteStateA handles request1.
ConcreteStateA wants to change the state of the context.
Context: Transition to ConcreteStateB.
ConcreteStateB handles request2.
ConcreteStateB wants to change the state of the context.
Context: Transition to ConcreteStateA.
复制代码
评论