PHP设计模式之状态模式定义与用法详解


Posted in PHP onApril 02, 2018

本文实例讲述了PHP设计模式之状态模式定义与用法。分享给大家供大家参考,具体如下:

什么是状态设计模式

当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。

什么时候使用状态模式

对象中频繁改变非常依赖于条件语句。 就其自身来说, 条件语句本身没有什么问题(如switch语句或带else子句的语句),不过, 如果选项太多, 以到程序开始出现混乱, 或者增加或改变选项需要花费太多时间, 甚至成为一种负担, 这就出现了问题

对于状态设计模式, 每个状态都有自己的具体类, 它们实现一个公共接口. 我们不用查看对象的控制流, 而是从另一个角度来考虑, 即对象的状态.

状态机是一个模型, 其重点包括不同的状态, 一个状态到另一个状态的变迁, 以及导致状态改变的触发器.

以开灯关灯为例子, 状态模型的本质分为3点:

①状态(关灯和开灯)
②变迁(从关灯到开灯, 以及从开灯到关灯)
③触发器(灯开关)

所以状态模式都需要一个参与者来跟踪对象所处的状态. 以Light为例, Light需要知道当前状态是什么.

示例:开灯关灯

Light.php

<?php
class Light
{
  private $offState; //关闭状态
  private $onState;  //开启状态
  private $currentState; //当前状态
  public function __construct()
  {
    $this->offState = new OffState($this);
    $this->onState = new OnState($this);
    //开始状态为关闭状态Off
    $this->currentState = $this->offState;
  }
  //调用状态方法触发器
  public function turnLightOn()
  {
    $this->currentState->turnLightOn();
  }
  public function turnLightOff()
  {
    $this->currentState->turnLightOff();
  }
  //设置当前状态
  public function setState(IState $state)
  {
    $this->currentState = $state;
  }
  //获取状态
  public function getOnState()
  {
    return $this->onState;
  }
  public function getOffState()
  {
    return $this->offState;
  }
}

在构造函数中, Light实例化IState实现的两个实例-----一个对应关, 一个对应开

$this->offState = new OffState($this);
$this->onState = new OnState($this);

这个实例化过程用到了一种递归, 称为自引用(self-referral)

构造函数参数中的实参写为$this, 这是Light类自身的一个引用. 状态类希望接收一个Light类实例做参数,.

setState方法是为了设置一个当前状态 需要一个状态对象作为实参, 一旦触发一个状态, 这个状态就会向Light类发送信息, 指定当前状态.

状态实例

IState接口

IState.php

<?php
interface IState
{
  public function turnLightOn();
  public function turnLightOff();
}

该接口的实现类

OnState.php

<?php
class OnState implements IState
{
  private $light;
  public function __construct(Light $light)
  {
    $this->light = $light;
  }
  public function turnLightOn()
  {
    echo "灯已经打开了->不做操作<br />";
  }
  public function turnLightOff()
  {
    echo "灯关闭!看不见帅哥chenqionghe了!<br />";
    $this->light->setState($this->light->getOffState());
  }
}

OffState.php

<?php
class OffState implements IState
{
  private $light;
  public function __construct(Light $light)
  {
    $this->light = $light;
  }
  public function turnLightOn()
  {
    echo "灯打开!可以看见帅哥chenqionghe了!<br />";
    $this->light->setState($this->light->getOnState());
  }
  public function turnLightOff()
  {
    echo "灯已经关闭了->不做操作<br />";
  }
}

默认状态是OffState, 它必须实现IState方法turnLightOn和turnLightOff, Light调用turnLightOn方法, 会显示(灯打开!可以看见帅哥chenqionghe了), 然后将OnState设置为当前状态, 不过,如果是调用 OffState的turnLightOff方法, 就只有提示灯已经被关闭了 不会有其他动作.

客户

Client的所有请求都是通过Light发出, Client和任何状态类之间都没有直接连接, 包括IState接口.下面的Client显示了触发两个状态中所有方法的请求.

Client.php

<?php
function __autoload($class_name)
{
  include_once $class_name.'.php';
}
class Client
{
  private $light;
  public function __construct()
  {
    $this->light = new Light();
    $this->light->turnLightOn();
    $this->light->turnLightOn();
    $this->light->turnLightOff();
    $this->light->turnLightOff();
  }
}
$worker = new Client();

增加状态

对于所有的设计模式来说,很重要的一个方面是: 利用这些设计模式可以很容易地做出修改. 与其他模式一样,状态模式也很易于更新和改变. 下面在这个灯的示例上再加两个状态:更亮(Brighter)和最亮(Brightest)

现在变成了4个状态, 序列有所改变. '关'(off)状态只能变到"开"(on)状态, on状态不能变到off状态. on状态只能变到"更亮"(brighter)状态和"最亮"(brightest)状态. 只能最亮状态才可能变到关状态.

改变接口

要改变的第一个参与者是接口IState, 这个接口中必须指定相应的方法, 可以用来迁移到brighter和brightest状态.

IState.php

<?php
interface IState
{
  public function turnLightOn();
  public function turnLightOff();
  public function turnBrighter();
  public function turnBrightest();
}

现在所有状态类都必须包含这4个方法, 它们都需要结合到Light类中.

改变状态

状态设计模式中有改变时, 这些新增的改变会对模式整体的其他方面带来影响. 不过, 增加改变相当简单, 每个状态只有一个特定的变迁.

四个状态

OnState.php

<?php
class OnState implements IState
{
  private $light;
  public function __construct(Light $light)
  {
    $this->light = $light;
  }
  public function turnLightOn()
  {
    echo "不合法的操作!<br />";
  }
  public function turnLightOff()
  {
    echo "灯关闭!看不见帅哥chenqionghe了!<br />";
    $this->light->setState($this->light->getOffState());
  }
  public function turnBrighter()
  {
    echo "灯更亮了, 看帅哥chenqionghe看得更真切了!<br />";
    $this->light->setState($this->light->getBrighterState());
  }
  public function turnBrightest()
  {
    echo "不合法的操作!<br />";
  }
}

OffState.php

<?php
class OffState implements IState
{
  private $light;
  public function __construct(Light $light)
  {
    $this->light = $light;
  }
  public function turnLightOn()
  {
    echo "灯打开!可以看见帅哥chenqionghe了!<br />";
    $this->light->setState($this->light->getOnState());
  }
  public function turnLightOff()
  {
    echo "不合法的操作!<br />";
  }
  public function turnBrighter()
  {
    echo "不合法的操作!<br />";
  }
  public function turnBrightest()
  {
    echo "不合法的操作!<br />";
  }
}

Brighter.php

<?php
class BrighterState implements IState
{
  private $light;
  public function __construct(Light $light)
  {
    $this->light = $light;
  }
  public function turnLightOn()
  {
    echo "不合法的操作!<br />";
  }
  public function turnLightOff()
  {
    echo "不合法的操作!<br />";
  }
  public function turnBrighter()
  {
    echo "不合法的操作!<br />";
  }
  public function turnBrightest()
  {
    echo "灯最亮了, 看帅哥chenqionghe已经帅到无敌!<br />";
    $this->light->setState($this->light->getBrightestState());
  }
}

Brightest.php

<?php
class BrightestState implements IState
{
  private $light;
  public function __construct(Light $light)
  {
    $this->light = $light;
  }
  public function turnLightOn()
  {
    echo "灯已经打开了->不做操作<br />";
  }
  public function turnLightOff()
  {
    echo "灯关闭!看不见帅哥chenqionghe了!<br />";
    $this->light->setState($this->light->getOffState());
  }
  public function turnBrighter()
  {
    echo "不合法的操作!<br />";
  }
  public function turnBrightest()
  {
    echo "不合法的操作!<br />";
  }
}

更新Light类

Light.php

<?php
class Light
{
  private $offState; //关闭状态
  private $onState;  //开启状态
  private $brighterState; //更亮状态
  private $brightestState;//最亮状态
  private $currentState; //当前状态
  public function __construct()
  {
    $this->offState = new OffState($this);
    $this->onState = new OnState($this);
    $this->brighterState = new BrighterState($this);
    $this->brightestState = new BrightestState($this);
    //开始状态为关闭状态Off
    $this->currentState = $this->offState;
  }
  //调用状态方法触发器
  public function turnLightOn()
  {
    $this->currentState->turnLightOn();
  }
  public function turnLightOff()
  {
    $this->currentState->turnLightOff();
  }
  public function turnLightBrighter()
  {
    $this->currentState->turnBrighter();
  }
  public function turnLigthBrightest()
  {
    $this->currentState->turnBrightest();
  }
  //设置当前状态
  public function setState(IState $state)
  {
    $this->currentState = $state;
  }
  //获取状态
  public function getOnState()
  {
    return $this->onState;
  }
  public function getOffState()
  {
    return $this->offState;
  }
  public function getBrighterState()
  {
    return $this->brighterState;
  }
  public function getBrightestState()
  {
    return $this->brightestState;
  }
}

更新客户

<?php
function __autoload($class_name)
{
  include_once $class_name.'.php';
}
class Client
{
  private $light;
  public function __construct()
  {
    $this->light = new Light();
    $this->light->turnLightOn();
    $this->light->turnLightBrighter();
    $this->light->turnLigthBrightest();
    $this->light->turnLightOff();
    $this->light->turnLigthBrightest();
  }
}
$worker = new Client();

运行结果如下

灯打开!可以看见帅哥chenqionghe了!
灯更亮了, 看帅哥chenqionghe看得更真切了!
灯最亮了, 看帅哥chenqionghe已经帅到无敌!
灯关闭!看不见帅哥chenqionghe了!
不合法的操作!

九宫格移动示例

九宫格的移动分为4个移动:

上(Up)
下(Down)
左(Left)
右(Right)

对于这些移动,规则是要求单元格之间不能沿对角线方向移动. 另外, 从一个单元格移动到下一个单元格时, 一次只能移动一个单元格

要使用状态设计模式来建立一个九宫格移动示例,

建立接口

IMatrix.php

<?php
interface IMatrix
{
  public function goUp();
  public function goDown();
  public function goLeft();
  public function goRight();
}

虽然这个状态设计模式有9个状态, 分别对应九个单元格, 但一个状态最多只需要4个变迁

上下文

对于状态中的4个变迁或移动方法, 上下文必须提供相应方法来调用这些变迁方法, 另外还要完成各个状态的实例化.

Context.php

<?php
class Context
{
  private $cell1;
  private $cell2;
  private $cell3;
  private $cell4;
  private $cell5;
  private $cell6;
  private $cell7;
  private $cell8;
  private $cell9;
  private $currentState;
  public function __construct()
  {
    $this->cell1 = new Cell1State($this);
    $this->cell2 = new Cell2State($this);
    $this->cell3 = new Cell3State($this);
    $this->cell4 = new Cell4State($this);
    $this->cell5 = new Cell5State($this);
    $this->cell6 = new Cell6State($this);
    $this->cell7 = new Cell7State($this);
    $this->cell8 = new Cell8State($this);
    $this->cell9 = new Cell9State($this);
    $this->currentState = $this->cell5;
  }
  //调用方法
  public function doUp()
  {
    $this->currentState->goUp();
  }
  public function doDown()
  {
    $this->currentState->goDown();
  }
  public function doLeft()
  {
    $this->currentState->goLeft();
  }
  public function doRight()
  {
    $this->currentState->goRight();
  }
  //设置当前状态
  public function setState(IMatrix $state)
  {
    $this->currentState = $state;
  }
  //获取状态
  public function getCell1State()
  {
    return $this->cell1;
  }
  public function getCell2State()
  {
    return $this->cell2;
  }
  public function getCell3State()
  {
    return $this->cell3;
  }
  public function getCell4State()
  {
    return $this->cell4;
  }
  public function getCell5State()
  {
    return $this->cell5;
  }
  public function getCell6State()
  {
    return $this->cell6;
  }
  public function getCell7State()
  {
    return $this->cell7;
  }
  public function getCell8State()
  {
    return $this->cell8;
  }
  public function getCell9State()
  {
    return $this->cell9;
  }
}

状态

9个状态表示九宫格中的不同单元格, 为了唯一显示单元格,会分别输出相应到达的单元格数字, 这样能够更清楚地看出穿过矩阵的路线.

Cell1State

<?php
class Cell1State implements IMatrix
{
  private $context;
  public function __construct(Context $contextNow)
  {
    $this->context = $contextNow;
  }
  public function goLeft()
  {
    echo '不合法的移动!<br />';
  }
  public function goRight()
  {
    echo '走到<strong>2</strong><br />';
    $this->context->setState($this->context->getCell2State());
  }
  public function goUp()
  {
    echo '不合法的移动!<br />';
  }
  public function goDown()
  {
    echo '走到<strong>4</strong><br />';
    $this->context->setState($this->context->getCell4State());
  }
}

Cell2State

<?php
class Cell2State implements IMatrix
{
  private $context;
  public function __construct(Context $contextNow)
  {
    $this->context = $contextNow;
  }
  public function goLeft()
  {
    echo '走到<strong>1</strong><br />';
    $this->context->setState($this->context->getCell1State());
  }
  public function goRight()
  {
    echo '走到<strong>3</strong><br />';
    $this->context->setState($this->context->getCell3State());
  }
  public function goUp()
  {
    echo '不合法的移动!<br />';
  }
  public function goDown()
  {
    echo '走到<strong>5</strong><br />';
    $this->context->setState($this->context->getCell5State());
  }
}

Cell3State

<?php
class Cell3State implements IMatrix
{
  private $context;
  public function __construct(Context $contextNow)
  {
    $this->context = $contextNow;
  }
  public function goLeft()
  {
    echo '走到<strong>2</strong><br />';
    $this->context->setState($this->context->getCell2State());
  }
  public function goRight()
  {
    echo '不合法的移动!<br />';
  }
  public function goUp()
  {
    echo '不合法的移动!<br />';
  }
  public function goDown()
  {
    echo '走到<strong>6</strong><br />';
    $this->context->setState($this->context->getCell6State());
  }
}

Cell4State

<?php
class Cell4State implements IMatrix
{
  private $context;
  public function __construct(Context $contextNow)
  {
    $this->context = $contextNow;
  }
  public function goLeft()
  {
    echo '不合法的移动!<br />';
  }
  public function goRight()
  {
    echo '走到<strong>5</strong><br />';
    $this->context->setState($this->context->getCell5State());
  }
  public function goUp()
  {
    echo '走到<strong>1</strong><br />';
    $this->context->setState($this->context->getCell1State());
  }
  public function goDown()
  {
    echo '走到<strong>7</strong><br />';
    $this->context->setState($this->context->getCell7State());
  }
}

Cell5State

<?php
class Cell5State implements IMatrix
{
  private $context;
  public function __construct(Context $contextNow)
  {
    $this->context = $contextNow;
  }
  public function goLeft()
  {
    echo '走到<strong>4</strong><br />';
    $this->context->setState($this->context->getCell4State());
  }
  public function goRight()
  {
    echo '走到<strong>6</strong><br />';
    $this->context->setState($this->context->getCell6State());
  }
  public function goUp()
  {
    echo '走到<strong>2</strong><br />';
    $this->context->setState($this->context->getCell2State());
  }
  public function goDown()
  {
    echo '走到<strong>8</strong><br />';
    $this->context->setState($this->context->getCell8State());
  }
}

Cell6State

<?php
class Cell6State implements IMatrix
{
  private $context;
  public function __construct(Context $contextNow)
  {
    $this->context = $contextNow;
  }
  public function goLeft()
  {
    echo '走到<strong>5</strong><br />';
    $this->context->setState($this->context->getCell5State());
  }
  public function goRight()
  {
    echo '不合法的移动!<br />';
  }
  public function goUp()
  {
    echo '走到<strong>3</strong><br />';
    $this->context->setState($this->context->getCell3State());
  }
  public function goDown()
  {
    echo '走到<strong>9</strong><br />';
    $this->context->setState($this->context->getCell9State());
  }
}

Cell7State

<?php
class Cell7State implements IMatrix
{
  private $context;
  public function __construct(Context $contextNow)
  {
    $this->context = $contextNow;
  }
  public function goLeft()
  {
    echo '不合法的移动!<br />';
  }
  public function goRight()
  {
    echo '走到<strong>8</strong><br />';
    $this->context->setState($this->context->getCell8State());
  }
  public function goUp()
  {
    echo '走到<strong>4</strong><br />';
    $this->context->setState($this->context->getCell4State());
  }
  public function goDown()
  {
    echo '不合法的移动!<br />';
  }
}

Cell8State

<?php
class Cell8State implements IMatrix
{
  private $context;
  public function __construct(Context $contextNow)
  {
    $this->context = $contextNow;
  }
  public function goLeft()
  {
    echo '走到<strong>7</strong><br />';
    $this->context->setState($this->context->getCell7State());
  }
  public function goRight()
  {
    echo '走到<strong>9</strong><br />';
    $this->context->setState($this->context->getCell9State());
  }
  public function goUp()
  {
    echo '走到<strong>5</strong><br />';
    $this->context->setState($this->context->getCell5State());
  }
  public function goDown()
  {
    echo '不合法的移动!<br />';
  }
}

Cell9State

<?php
class Cell9State implements IMatrix
{
  private $context;
  public function __construct(Context $contextNow)
  {
    $this->context = $contextNow;
  }
  public function goLeft()
  {
    echo '走到<strong>8</strong><br />';
    $this->context->setState($this->context->getCell8State());
  }
  public function goRight()
  {
    echo '不合法的移动!<br />';
  }
  public function goUp()
  {
    echo '走到<strong>6</strong><br />';
    $this->context->setState($this->context->getCell6State());
  }
  public function goDown()
  {
    echo '不合法的移动!<br />';
  }
}

要想有效地使用状态设计模式, 真正的难点在于要想象现实或模拟世界是怎么样

客户Client

下面从单元格5开始进行一个上,右,下, 下,左,上的移动

Client.php

<?php
function __autoload($class_name)
{
  include_once $class_name.'.php';
}
class Client
{
  private $context;
  public function __construct()
  {
    $this->context = new Context();
    $this->context->doUp();
    $this->context->doRight();
    $this->context->doDown();
    $this->context->doDown();
    $this->context->doLeft();
    $this->context->doUp();
  }
}
$worker = new Client();

运行结果如下

走到2
走到3
走到6
走到9
走到8
走到5

状态模式与PHP

很多人把状态设计模式看做是实现模拟器和游戏的主要方法.总的说来, 这确实是状态模式的目标,不过险些之外, 状态模型(状态引擎)和状态设计模式在PHP中也有很多应用.用PHP完成更大的项目时, 包括Facebook和WordPress, 会有更多的新增特性和当前状态需求.对于这种不断有改变和增长的情况, 就可以采用可扩展的状态模式来管理.

PHP开发人员如何创建包含多个状态的程序, 将决定状态模式的使用范围. 所以不仅状态机在游戏和模拟世界中有很多应用, 实际上状态模型还有更多适用的领域.只要PHP程序的用户会用到一组有限的状态, 开发人员就可以使用状态设计模式.

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
Ha0k 0.3 PHP 网页木马修改版
Oct 11 PHP
Php Ctemplate引擎开发相关内容
Mar 03 PHP
Session服务器配置指南与使用经验的深入解析
Jun 17 PHP
PHP图片等比缩放类SimpleImage使用方法和使用实例分享
Apr 10 PHP
php快递单号查询接口使用示例
May 05 PHP
PHP实现的memcache环形队列类实例
Jul 28 PHP
详解WordPress开发中get_header()获取头部函数的用法
Jan 08 PHP
CodeIgniter自定义控制器MY_Controller用法分析
Jan 20 PHP
一段实用的php验证码函数
May 19 PHP
php中引用符号(&amp;)的使用详细介绍
Dec 06 PHP
php技巧小结【推荐】
Jan 19 PHP
php使用json-schema模块实现json校验示例
Sep 28 PHP
PHP设计模式之模板方法模式定义与用法详解
Apr 02 #PHP
PHP实现动态获取函数参数的方法示例
Apr 02 #PHP
PHP调用其他文件中的类
Apr 02 #PHP
为何说PHP引用是个坑,要慎用
Apr 02 #PHP
PHP实现的一致性Hash算法详解【分布式算法】
Mar 31 #PHP
PHP实现基于PDO扩展连接PostgreSQL对象关系数据库示例
Mar 31 #PHP
ThinkPHP框架中使用Memcached缓存数据的方法
Mar 31 #PHP
You might like
学习使用PHP数组
2006/10/09 PHP
php使用异或实现的加密解密实例
2013/09/04 PHP
PHP下SSL加密解密、验证、签名方法(很简单)
2020/06/28 PHP
Laravel如何使用Redis共享Session
2018/02/23 PHP
JSON 客户端和服务器端的格式转换
2009/08/27 Javascript
关于 文本框默认值 的操作js代码
2012/01/12 Javascript
jQuery动态改变图片显示大小(修改版)的实现思路及代码
2013/12/24 Javascript
使用javascript为网页增加夜间模式
2014/01/26 Javascript
javascript根据像素点取位置示例
2014/01/27 Javascript
邮箱下拉自动填充选择示例代码附图
2014/04/03 Javascript
javascript判断数组内是否重复的方法
2015/04/21 Javascript
jQuery实现TAB选项卡切换特效简单演示
2016/03/04 Javascript
Bootstrap源码解读媒体对象、列表组和面板(10)
2016/12/26 Javascript
BootstrapTable请求数据时设置超时(timeout)的方法
2017/01/22 Javascript
Linux CentOS系统下安装node.js与express的方法
2017/04/01 Javascript
JS实现获取图片大小和预览的方法完整实例【兼容IE和其它浏览器】
2017/04/24 Javascript
node跨域转发 express+http-proxy-middleware的使用
2018/05/31 Javascript
JavaScript中break、continue和return的用法区别实例分析
2020/03/02 Javascript
通过实例了解JS执行上下文运行原理
2020/06/17 Javascript
Vue使用鼠标在Canvas上绘制矩形
2020/12/24 Vue.js
python备份文件以及mysql数据库的脚本代码
2013/06/10 Python
Python实现获取网站PR及百度权重
2015/01/21 Python
python装饰器初探(推荐)
2016/07/21 Python
Python设计模式之抽象工厂模式
2016/08/25 Python
python算法演练_One Rule 算法(详解)
2017/05/17 Python
Python将列表中的元素转化为数字并排序的示例
2019/12/25 Python
利用python+ffmpeg合并B站视频及格式转换的实例代码
2020/11/24 Python
涉及车辆房产分割的离婚协议书范文
2014/10/12 职场文书
作文评语集锦
2014/12/25 职场文书
领导干部考核评语
2015/01/04 职场文书
公务员年度考核个人总结
2015/02/12 职场文书
综合办公室岗位职责
2015/04/11 职场文书
妈妈别哭观后感
2015/06/08 职场文书
2016年秋季运动会通讯稿
2015/11/25 职场文书
python数据库批量插入数据的实现(executemany的使用)
2021/04/30 Python
Android Canvas绘制文字横纵向对齐
2022/06/05 Java/Android