这篇文章主要介绍“讲解PHP设计模式入门之状态模式原理与实现方法”,在日常操作中,相信很多人在讲解PHP设计模式入门之状态模式原理与实现方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”讲解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 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();
到此,关于“讲解PHP设计模式入门之状态模式原理与实现方法”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。