本文实例讲述了php设计模式入门之状态模式原理与实现方法。分享给大家供大家参考,具体如下:
想必大家都用过自动售卖的自动饮料机吧,塞入硬币或纸币,选择想要的饮料,饮料就会在机器的下方滚出。大家有没有相关如果用程序去写一个饮料机要怎么样实现呢?
首先我们可以分享一下这部饮料机有几种状态
一、没有钱的状态
二、有钱的状态
三、售出的状态
四、销售一空的状态
好吧,知道了这些状态之后我们开始写代码了!
juicemachine.php
<?php/** * 饮料机 * @author ben * */class juicemachine{ /** * 糖果机一共存在四种状态:没钱,有钱,成功售出以及销售一空 * * 没钱的状态 * @var int */ const nomoney = 0; /** * 有钱的状态 * @var int */ const hasmoney = 1; /** * 成功售出的状态 * @var int */ const sold = 2; /** * 销售一空的状态 * @var int */ const soldout = 3; /** * 记录糖果机当前的状态,初始化状态为售空 * @var int */ private $_state = juicemachine::soldout; /** * 该变量用于记录饮料机中饮料的数量 */ private $_count; /** * 构造方法,最主要是用来初始化count和state属性的 */ public function __construct($count){ $this->_count = $count; //当饮料机中的饮料数量大于零时,将饮料机的状态重贺新春短信置为没有钱的状态。 if($this->_count > 0){ $this->_state = juicemachine::nomoney; } } /** * 投入硬币 */ public function inrtcoin(){ if($this->_state == juicemachine::hasmoney ){ echo "you can't inrt another coin!<br />"; }elif($this->_state == juicemachine::nomoney){ echo "you just inrt a coin<br />"; $this->_state = juicemachine::hasmoney; }elif($this->_state == juicemachine::sold){ echo "wait a minute, we are giving you a bottle of juice<br />"; }elif($this->_state == juicemachine::soldout){ echo "you can't inrt coin, the machine is already soldout<br />"; } } /** * 退回硬币 */ public function retreatcoin(){ if($this->_state == juicemachine::hasmoney ){ echo "coin return!<br />"; $this->_state = juicemachine::nomoney; }elif($this->_state == juicemachine::nomoney){ echo "you have'nt inrted a coin yet<br />"; }elif($this->_state == juicemachine::sold){ echo "sorry, you already clicked the botton<br />"; }elif($this->_state == juicemachine::soldout){ echo "you have'nt inrted a coin yet<br />"; } } /** * 点击饮料对应的按钮 */ public function clickbutton(){ if($this->_state == juicemachine::hasmoney ){ echo "you clicked, we are giving you a bottle of juice...<br />"; $this->_state = juicemachine::sold; //改变饮料机的状态为售出模式 $this->dispend(); }elif($this->_state == juicemachine::nomoney){ echo "you clicked,but you hav'nt inrted a coin yet<br />"; }elif($this->_state == juicemachine::sold){ echo "click twice does'nt get you two bottle of juice<br />"; }elif($this->_state == juicemachine::soldout){ echo "you clicked, but the machine is alrea学员兵dy soldout<br />"; } } /** * 发放饮料 */ public function dispend(){ if($this->_state == juicemachine::hasmoney ){ echo "plea click the button first<br />"; }elif($this->_state == juicemachine::nomoney){ echo "you need to pay first<br />"; }elif($this->_state == juicemachine::sold){ echo "now you get you juice<br />"; //饮料机中的饮料数量减一 $this->_count--; if($this->_count <= 0){ echo "opps, runing out of juice<br />"; //如果这时饮料机中没有饮料了,将饮料机的状态重置为销售一空 $this->_state = juicemachine::soldout; }el{ //将饮料机的状态重置为没有钱 $this->_state = juicemachine::nomoney; } }elif($this->_state == juicemachine::soldout){ //其实这种情况不应该出现 echo "opps, it appears that we don't have any juice left<br />"; } }}
index.php
<?phprequire_once 'juicemachine.php'; $juicemachine = new juicemachine(1); $juicemachine->inrtcoin();$juicemachine->clickbutton();
运行的结果是:
you just inrt a coin
you clicked, we are giving you a bottle of juice…
now you get you juice
opps, runing out of juice
到目前为止我们的程序运行良好,没有出现什么问题,但是从这些多重的if判断中你是否嗅到了坏代码的味道呢?有一天问题终于出现了,老板希望当用户点击按钮时有10%的概率拿到两瓶饮料,我们需要为饮料机多加一个状态,这时去修改代码就成为了一种灾难,而且很可能会影响到之前的代码,带来新的bug,看看状态模式如何帮助我们度过难关吧!
状态模式的官方定义是:状态模式允许对象在内部状态改变是改变它的行为,对象看起来好像是修改了它的类
用uml类图表示如下:
在我们这个项目中的实际类图如下:
具体实现代码:
state.php
<?phpinterface state{ /** * 插入硬币 */ public function inrtcoin(); /** * 回退硬币 */ public function retreatcoin(); /** * 点击按钮 */ public function clickbutton(); /** * 发放饮料 */ public function dispend();}
nomoneystate.php
<?phprequire_once 'state.php';class nomoneystate implements state{ /** * 饮料机的实例 * * @var object */ private $_juicemachine; /** * 构造方法,主要用于初始化饮料机实例 * */ public function __construct($juicemachine){ $this->_juicemachine = $juicemachine; } /* (non-phpdoc) * @e state::inrtcoin() */ public function inrtcoin() { // todo auto-generated method stub echo "you just inrt a coin<br />"; //将饮料机的状态切换成有钱的状态 $this->_juicemachine->tstate($this->_juicemachine->gethasmoneystate()); } /* (non-phpdoc) * @e state::retreatcoin() */ public function retreatcoin() { // todo auto-generated method stub echo "you have'nt inrted a coin yet<br />"; } /* (non-phpdoc) * @e state::clickbutton() */ public function clickbutton() { // todo auto-generated method stub echo "you clicked,but you hav'nt inrted a coin yet<br />"; } /* (non-phpdoc) * @e state::dispend() */ public function dispend() { // todo auto-generated method stub echo "you need to pay first<br />"; }}
hasmoneystate.php
<?phprequire_once 'state.php'; class hasmoneystate implements state{ /** * 饮料机的实例 * * @var object */ private $_juicemachine; /** * 构造方法,主要用于初始化饮料机实例 */ public function __construct($juicemachine) { $this->_juicemachine = $juicemachine; } /* * (non-phpdoc) @e state::inrtcoin() */ public function inrtcoin() { // todo auto-generated method stub echo "you can't inrt another coin!<br />"; } /* * (non-phpdoc) @e state::retreatcoin() */ public function retreatcoin() { // todo auto-generated method stub echo "coin return!<br />"; $this->_juicemachine->tstate($this->_juicemachine->getnomoneystate()); } /* * (non-phpdoc) @e state::clickbutton() */ public function clickbutton() { // todo auto-generated method stub echo "you clicked, we are giving you a bottle of juice...<br />"; // 改变饮料机的状态为售出模式 $rand = mt_rand(0, 0); // 当随机数为0(即1/10的概率)并且饮料机中还有1瓶以上的饮料时 if ($rand == 0 && $this->_juicemachine->getcount() > 1) { $this->_juicemachine->tstate($this->_juicemachine->getwinnerstate()); } el { $this->_juicemachine->tstate($this->_juicemachine->getsoldstate()); } } /* * (non-phpdoc) @e state::dispend() */ public function dispend() { // todo auto-generated met学富五车的反义词hod stub echo "plea click the button first<br />"; }}
soldoutstate.php
<?phprequire_once 'state.php';class soldoutstate implements state{ /** * 饮料机的实例 * * @var object */ private $_juicemachine; /** * 构造方法,主要用于初始化饮料机实例 * */ public function __construct($juicemachine){ $this->_juicemachine = $juicemachine; } /* (non-phpdoc) * @e state::inrtcoin() */ public function inrtcoin() { // todo auto-generated method stub echo "you can't inrt coin, the machine is already soldout<br />"; } /* (non-phpdoc) * @e state::retreatcoin() */ public function retreatcoin() { // todo auto-generated method stub echo "you have'nt inrted a coin yet<br />"; } /* (non-phpdoc) * @e state::clickbutton() */ public function clickbutton() { // todo auto-generated method stub echo "you clicked, but the machine is already soldout<br />"; } /* (non-phpdoc) * @e state::dispend() */ public function dispend() { // todo auto-generated method stub echo "opps, it appears that we don't have any juice left<br />"; }}
soldstate.php
<?phprequire_once 'state.php';class soldstate implements state{ /** * 饮料机的实例 * * @var object */ private $_juicemachine; /** * 构造方法,主要用于初始化饮料机实例 * */ public function __construct($juicemachine){ $this->_juicemachine = $juicemachine; } /* (non-phpdoc) * @e state::inrtcoin() */ public function inrtcoin() { // todo auto-generated method stub echo "wait a minute, we are giving you a bottle of juice<br />"; } /* (non-phpdoc) * @e state::retreatcoin() */ public function retreatcoin() { // todo auto-generated method stub echo "sorry, you already clicked the botton<br />"; } /* (non-phpdoc) * @e state::clickbutton() */ public function clickbutton() { // todo auto-generated method stub echo "click twice does'nt get you two bottle of juice<br />"; } /* (non-phpdoc) * @e state::dispend() */ public function dispend() { $this->_juicemachine->decjuice(); if($this->_juicemachine->getcount() <= 0){ echo "opps, runing out of juice<br />"; //如果这时饮料机中没有饮料了,将饮料机的状态重置为销售一空 $this->_juicemachine->tstate($this->_juicemachine->getsoldoutstate()); }el{ //将饮料机的状态重置为没有钱 $this->_juicemachine->tstate($this->_juicemachine->getnomoneystate()); } } }
winnerstate.php
<?phprequire_once 'state.php'; class winnerstate implements state{ /** * 饮料机的实例 * * @var object */ private $_juicemachine; /** * 构造方法,主要用于初始化饮料机实例 */ public function __construct($juicemachine) { $this->_juicemachine = $juicemachine; } /* * (non-phpdoc) @e state::inrtcoin() */ public function inrtcoin() { // todo auto-generated method stub echo "wait a minute, we are giving you a bottle of juice<br />"; } /* * (non-phpdoc) @e state::retreatcoin() */ public function retreatcoin() { // todo auto-generated method stub echo "sorry, you already clicked the botton<br />"; } /* * (non-phpdoc) @e要你对我xxx state::clickbutton() */ public function clickbutton() { // todo auto-generated method stub echo "click twice does'nt get you two bottle of juice<br />"; } /* * (non-phpdoc) @e state::dispend() */ public function dispend() { echo "you are a winner! you get two bottle of juice!<br />"; $this->_juicemachine->decjuice(); if ($this->_juicemachine->getcount() > 0) { $this->_juicemachine->decjuice(); if ($this->_juicemachine->getcount() <= 0) { echo "opps, runing out of juice<br />"; // 如果这时饮料机中没有饮料了,将饮料机的状态重置为销售一空 $this->_juicemachine->tstate($this->_juicemachine->getsoldoutstate()); } el { // 将饮料机的状态重置为没有钱 $this->_juicemachine->tstate($this->_juicemachine->getsoldoutstate()); } } el { echo "opps, runing out of juice<br />"; // 如果这时饮料机中没有饮料了,将饮料机的状态重置为销售一空 $this->_juicemachine->tstate($this->_juicemachine->getsoldoutstate()); } }}
juicemachine.php
<?phprequire_once './state/nomoneystate.php';require_once './state/hasmoneystate.php';require_once './state/soldstate.php';require_once './state/soldoutstate.php';require_once './state/winnerstate.php'; class juicemachine{ /** * 记录糖果机当前的状态,初始化状态为售空 * * @var object */ private $_state; /** * 该变量用于记录饮料机中饮料的数量 */ private $_count; /** * 构造方法,最主要是用来初始化count和state属性的 */ public function __construct($count) { $this->_state = new soldoutstate($this); $this->_count = $count; // 当饮料机中的饮料数量大于零时,将饮料机的状态重置为没有钱的状态。 if ($this->_count > 0) { $this->_state = new nomoneystate($this); } } /* * (non-phpdoc) @e state::inrtcoin() */ public function inrtcoin() { // todo auto-generated method stub $this->_state->inrtcoin(); } /* * (non-phpdoc) @e state::retreatcoin() */ public function retreatcoin() { // todo auto-generated method stub $this->_state->retreatcoin(); } /* * (non-phpdoc) @e state::clickbutton() */ public function clickbutton() { $this->_state->clickbutton(); //其实发放糖果是在用户点击完按钮后机器内部进行的所有没有必要再写一个dispend方法 $this->_state->dispend(); } /** * 设置糖果机的状态 * * @param state $state */ public function tstate(state $state) { $this->_state = $state; } /** * 获取没有钱的状态 */ public function getnomoneystate(){ return new nomoneystate($this); } /** * 获取有钱的状态 */ public function gethasmoneystate(){ return new hasmoneystate($this); } /** * 获取售出的状态 */ public function getsoldstate(){ return new soldstate($this); } /** * 获取销售一空的状态 */ public function getsoldoutstate(){ return new soldoutstate($this); } /** * 获取幸运者的状态 */ p上网的好处ublic function getwinnerstate(){ return new winnerstate($this); } /** * 获取饮料机中饮料的数量 */ public function getcount(){ return $this->_count; } /** * 将饮料数量减一 */ public function decjuice(){ echo "now you get you juice<br />"; //饮料机中的饮料数量减一 $this->_count--; } }
index.php
<?phprequire_once 'juicemachine.php'; $juicemachine = new juicemachine(2); $juicemachine->inrtcoin();$juicemachine->clickbutton();
本文发布于:2023-04-08 19:15:17,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/e97e1f30d03366b6f886fb7acbfc0671.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:PHP设计模式入门之状态模式原理与实现方法分析.doc
本文 PDF 下载地址:PHP设计模式入门之状态模式原理与实现方法分析.pdf
留言与评论(共有 0 条评论) |