设计模式之状态模式–状态机的实现原理
状态模式
是根据状态的改变触发一些动作或者行为。
当一个对象的内在状态改变时可以改变其行为,这个对象看起来像是改变了其类。
为什么用使用状态模式
状态模式
主要有三部分状态
、事件
、动作
。
通过一些事件会触发状态的改变,状态的改变有时候也会出发一些动作。
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的状态判断逻辑简化。
对于一个有各种状态,并且每种状态很复杂的就可以使用状态模式。不过对于状态来说最先想到的应该是使用if-else
来判断状态然后执行状态逻辑吧。
比如物流状态,假设有打包中
、运输中
、配送中
、已签收
。当然这个例子比较简单,没有那么复杂的状态交互。
if ($status == '打包中') {
} else if ($status == '运输中') {
} else if ($status == '配送中') {
} else if ($status == '已签收') {
}
这个时候如果要增加一个状态就需要修改这个if-else
,这里和业务是强耦合的,修改是很有问题的,那么使用状态模式把这些状态分离出来呢
php 实现状态模式
定义一个状态类
abstract class State {
abstract function change(Worker $w);
}
由于有四个状态,所以分离出四个状态类
class package extends State{
function change(Worker $w) {
//执行动作或者行为,比如变为打包中后还有什么操作
//执行完以后改变当前状态为运输中
$w->setState(new transport)
}
}
class transport extends State{
function change(Worker $w) {
//执行动作或者行为,比如运输中后还有什么操作
//执行完以后改变当前状态为配送中
$w->setState(new delivery)
}
}
class delivery extends State{
function change(Worker $w) {
//执行动作或者行为,比如配送中后还有什么操作
//执行完以后改变当前状态为已签收
$w->setState(new end)
}
}
class end extends State{
function change(Worker $W) {
//已经签收不能在改变状态了
return '不能改变了'
}
}
接下来有一个Worker类来管理状态
class Worker{
private $state;
function __construct() {
//初始化第一个状态
$this->state = new package();
}
//暴露一个改变当前状态的方法
function setState(State $state) {
$this->state = $state;
}
//给客户端暴露一个操作状态的接口,也就是事件,比如发生配送人开始配送了,那么状态需要从运输中改变成配送中
function change() {
//现在不需要判断了,只要根据当前状态来执行就可以了。
$this->state->change($this);
}
}
代码放在了我的github上面。