PHP状态模式实现自动售卖机出饮料机状态是怎样
Admin 2022-09-23 群英技术资讯 339 次浏览
想必大家都用过自动售卖的自动饮料机吧,塞入硬币或纸币,选择想要的饮料,饮料就会在机器的下方滚出。大家有没有相关如果用程序去写一个饮料机要怎么样实现呢?
首先我们可以分享一下这部饮料机有几种状态
一、没有钱的状态
二、有钱的状态
三、售出的状态
四、销售一空的状态
好吧,知道了这些状态之后我们开始写代码了!
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 insertCoin(){ if($this->_state == JuiceMachine::HASMONEY ){ echo "you can't insert another coin!<br />"; }elseif($this->_state == JuiceMachine::NOMONEY){ echo "you just insert a coin<br />"; $this->_state = JuiceMachine::HASMONEY; }elseif($this->_state == JuiceMachine::SOLD){ echo "wait a minute, we are giving you a bottle of juice<br />"; }elseif($this->_state == JuiceMachine::SOLDOUT){ echo "you can't insert coin, the machine is already soldout<br />"; } } /** * 退回硬币 */ public function retreatCoin(){ if($this->_state == JuiceMachine::HASMONEY ){ echo "coin return!<br />"; $this->_state = JuiceMachine::NOMONEY; }elseif($this->_state == JuiceMachine::NOMONEY){ echo "you have'nt inserted a coin yet<br />"; }elseif($this->_state == JuiceMachine::SOLD){ echo "sorry, you already clicked the botton<br />"; }elseif($this->_state == JuiceMachine::SOLDOUT){ echo "you have'nt inserted 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(); }elseif($this->_state == JuiceMachine::NOMONEY){ echo "you clicked,but you hav'nt inserted a coin yet<br />"; }elseif($this->_state == JuiceMachine::SOLD){ echo "click twice does'nt get you two bottle of juice<br />"; }elseif($this->_state == JuiceMachine::SOLDOUT){ echo "you clicked, but the machine is already soldout<br />"; } } /** * 发放饮料 */ public function dispend(){ if($this->_state == JuiceMachine::HASMONEY ){ echo "please click the button first<br />"; }elseif($this->_state == JuiceMachine::NOMONEY){ echo "you need to pay first<br />"; }elseif($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; }else{ //将饮料机的状态重置为没有钱 $this->_state = JuiceMachine::NOMONEY; } }elseif($this->_state == JuiceMachine::SOLDOUT){ //其实这种情况不应该出现 echo "opps, it appears that we don't have any juice left<br />"; } } }
index.php
<?php require_once 'JuiceMachine.php'; $juiceMachine = new JuiceMachine(1); $juiceMachine->insertCoin(); $juiceMachine->clickButton();
运行的结果是:
you just insert 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
<?php interface State{ /** * 插入硬币 */ public function insertCoin(); /** * 回退硬币 */ public function retreatCoin(); /** * 点击按钮 */ public function clickButton(); /** * 发放饮料 */ public function dispend(); }
NomoneyState.php
<?php require_once 'State.php'; class NomoneyState implements State{ /** * 饮料机的实例 * * @var object */ private $_juiceMachine; /** * 构造方法,主要用于初始化饮料机实例 * */ public function __construct($juiceMachine){ $this->_juiceMachine = $juiceMachine; } /* (non-PHPdoc) * @see State::insertCoin() */ public function insertCoin() { // TODO Auto-generated method stub echo "you just insert a coin<br />"; //将饮料机的状态切换成有钱的状态 $this->_juiceMachine->setState($this->_juiceMachine->getHasmoneyState()); } /* (non-PHPdoc) * @see State::retreatCoin() */ public function retreatCoin() { // TODO Auto-generated method stub echo "you have'nt inserted a coin yet<br />"; } /* (non-PHPdoc) * @see State::clickButton() */ public function clickButton() { // TODO Auto-generated method stub echo "you clicked,but you hav'nt inserted a coin yet<br />"; } /* (non-PHPdoc) * @see State::dispend() */ public function dispend() { // TODO Auto-generated method stub echo "you need to pay first<br />"; } }
HasmoneyState.php
<?php require_once 'State.php'; class HasmoneyState implements State { /** * 饮料机的实例 * * @var object */ private $_juiceMachine; /** * 构造方法,主要用于初始化饮料机实例 */ public function __construct($juiceMachine) { $this->_juiceMachine = $juiceMachine; } /* * (non-PHPdoc) @see State::insertCoin() */ public function insertCoin() { // TODO Auto-generated method stub echo "you can't insert another coin!<br />"; } /* * (non-PHPdoc) @see State::retreatCoin() */ public function retreatCoin() { // TODO Auto-generated method stub echo "coin return!<br />"; $this->_juiceMachine->setState($this->_juiceMachine->getNomoneyState()); } /* * (non-PHPdoc) @see 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->setState($this->_juiceMachine->getWinnerState()); } else { $this->_juiceMachine->setState($this->_juiceMachine->getSoldState()); } } /* * (non-PHPdoc) @see State::dispend() */ public function dispend() { // TODO Auto-generated method stub echo "please click the button first<br />"; } }
SoldoutState.php
<?php require_once 'State.php'; class SoldoutState implements State{ /** * 饮料机的实例 * * @var object */ private $_juiceMachine; /** * 构造方法,主要用于初始化饮料机实例 * */ public function __construct($juiceMachine){ $this->_juiceMachine = $juiceMachine; } /* (non-PHPdoc) * @see State::insertCoin() */ public function insertCoin() { // TODO Auto-generated method stub echo "you can't insert coin, the machine is already soldout<br />"; } /* (non-PHPdoc) * @see State::retreatCoin() */ public function retreatCoin() { // TODO Auto-generated method stub echo "you have'nt inserted a coin yet<br />"; } /* (non-PHPdoc) * @see State::clickButton() */ public function clickButton() { // TODO Auto-generated method stub echo "you clicked, but the machine is already soldout<br />"; } /* (non-PHPdoc) * @see 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
<?php require_once 'State.php'; class SoldState implements State{ /** * 饮料机的实例 * * @var object */ private $_juiceMachine; /** * 构造方法,主要用于初始化饮料机实例 * */ public function __construct($juiceMachine){ $this->_juiceMachine = $juiceMachine; } /* (non-PHPdoc) * @see State::insertCoin() */ public function insertCoin() { // TODO Auto-generated method stub echo "wait a minute, we are giving you a bottle of juice<br />"; } /* (non-PHPdoc) * @see State::retreatCoin() */ public function retreatCoin() { // TODO Auto-generated method stub echo "sorry, you already clicked the botton<br />"; } /* (non-PHPdoc) * @see State::clickButton() */ public function clickButton() { // TODO Auto-generated method stub echo "click twice does'nt get you two bottle of juice<br />"; } /* (non-PHPdoc) * @see State::dispend() */ public function dispend() { $this->_juiceMachine->decJuice(); if($this->_juiceMachine->getCount() <= 0){ echo "opps, runing out of juice<br />"; //如果这时饮料机中没有饮料了,将饮料机的状态重置为销售一空 $this->_juiceMachine->setState($this->_juiceMachine->getSoldoutState()); }else{ //将饮料机的状态重置为没有钱 $this->_juiceMachine->setState($this->_juiceMachine->getNomoneyState()); } } }
WinnerState.php
<?php require_once 'State.php'; class WinnerState implements State { /** * 饮料机的实例 * * @var object */ private $_juiceMachine; /** * 构造方法,主要用于初始化饮料机实例 */ public function __construct($juiceMachine) { $this->_juiceMachine = $juiceMachine; } /* * (non-PHPdoc) @see State::insertCoin() */ public function insertCoin() { // TODO Auto-generated method stub echo "wait a minute, we are giving you a bottle of juice<br />"; } /* * (non-PHPdoc) @see State::retreatCoin() */ public function retreatCoin() { // TODO Auto-generated method stub echo "sorry, you already clicked the botton<br />"; } /* * (non-PHPdoc) @see State::clickButton() */ public function clickButton() { // TODO Auto-generated method stub echo "click twice does'nt get you two bottle of juice<br />"; } /* * (non-PHPdoc) @see 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->setState($this->_juiceMachine->getSoldoutState()); } else { // 将饮料机的状态重置为没有钱 $this->_juiceMachine->setState($this->_juiceMachine->getSoldoutState()); } } else { echo "opps, runing out of juice<br />"; // 如果这时饮料机中没有饮料了,将饮料机的状态重置为销售一空 $this->_juiceMachine->setState($this->_juiceMachine->getSoldoutState()); } } }
JuiceMachine.php
<?php require_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) @see State::insertCoin() */ public function insertCoin() { // TODO Auto-generated method stub $this->_state->insertCoin(); } /* * (non-PHPdoc) @see State::retreatCoin() */ public function retreatCoin() { // TODO Auto-generated method stub $this->_state->retreatCoin(); } /* * (non-PHPdoc) @see State::clickButton() */ public function clickButton() { $this->_state->clickButton(); //其实发放糖果是在用户点击完按钮后机器内部进行的所有没有必要再写一个dispend方法 $this->_state->dispend(); } /** * 设置糖果机的状态 * * @param State $state */ public function setState(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); } /** * 获取幸运者的状态 */ public 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
<?php require_once 'JuiceMachine.php'; $juiceMachine = new JuiceMachine(2); $juiceMachine->insertCoin(); $juiceMachine->clickButton();
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
今天继续开始算法练习系列内容~本文的中心的问题“编写一个PHP程序,从给定的整数数组中创建新数组,将所有偶数移到所有奇数之前”。
php如何处理http请求超时?http请求超时不少朋友都有遇到过,那么我们应该如何解决呢?这篇文章就给大家介绍一下http请求超时可能出现的场景以及http请求超时解决方案。
对于删除数组元素大家应该都不陌生,那么如果是json对象数组删除元素,我们该如何做呢?对此,小编给大家介绍一下在JS中删除json对象数组元素的方法,感兴趣的朋友就继续往下看吧。
在之前的文章《PHP函数运用之:利用数组来输出文件的扩展名》中,我们介绍了两种利用数组来获取文件扩展名的方法。这次我们继续介绍获取文件扩展名的方法,看看利用字符串函数要怎么操作,感兴趣的朋友可以学习了解一下~
有关PHP的empty(),isset()还有is_null()这三个函数的用法讨论得已经很多了,而且很多资料也未必能说得很清楚。这里再重复一次,但不是从概念去说,直接用程序例子...
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008