状态模式(State)

还记得策略模式吗?

今天要介绍的状态模式,其实是策略模式的升级版,它们解决的都是逻辑中有大量if判断的问题;
在介绍state模式之前,有必要来回顾一个策略模式的使用方法:

if(isset($_GET['male'])){
$strategy = new maleShowStrategy();
}elseif(isset($_GET['female'])){
$strategy = new femaleShowStrategy();
}
//注意看这里上下,Page类不再依赖一种具体的策略,而是只需要绑定一个抽象的接口,这就是传说中的控制反转(IOC)。
$question = new Page($strategy);
$question->showPage();

状态模式就是对前面的if elseif 这块逻辑进行升级,不再用if else判断,而是根据类自身的状态判断。

实现

在写具体代码之前,我百度了一下网上的实现代码,我很惊讶似乎大多数案例都搞反了 状态类和业务类,不知道是我搞错了,还是网上的错误。大家暂且看我写的,有问题可以在文后评论。
//shop.php

class Shop {
private $handler;

//这里$state设置一个状态值
public $state;

//设置默认状态,和默认处理器
public function __construct() {
$this->state = 'male';
$this->handler = new maleHandler();
}
public function setHandler(Handler $handler) {
$this->handler = $handler;
}
public function show() {
$this->handler->handle($this);
}
}
#handler.php 业务处理接口类
interface Handler {
public function handle(Shop $shop);
}
#maleHandler.php 男性业务处理类
class maleHandler implements Handler
{
public function handle(Shop $shop)
{
if($shop->state =="male"){
echo '展示男性商品目录',PHP_EOL;
}else{
$shop->setHandler(new femaleHandler());
$shop->show();
}
}
}
#femaleHandler.php 女性业务处理类
class femaleHandler implements Handler
{
public function handle(Shop $shop)
{
if($shop->state =="female"){
echo '展示女性商品目录',PHP_EOL;
}else{
$shop->setHandler(new maleHandler());
$shop->show();
}
}
}

使用:

$shop = new Shop;
$shop->state ="male";
$shop->show();
//展示男性商品目录
$shop->state ="female";
$shop->show();
//展示女性商品目录

我们看到这是一种更厉害的封装,在客户端这一块,if else不见了,甚至连策略类的注入也不见了。
看上去很清爽。
但其实,在后台的实现,比之前复杂了不少,你需要在每一个handler类里面进行条件判断。

tags: PHP,设计模式