您现在的位置是:网站首页> 编程资料编程资料

PHP设计模式入门之状态模式原理与实现方法分析_php实例_

2023-05-25 261人已围观

简介 PHP设计模式入门之状态模式原理与实现方法分析_php实例_

本文实例讲述了PHP设计模式入门之状态模式原理与实现方法。分享给大家供大家参考,具体如下:

想必大家都用过自动售卖的自动饮料机吧,塞入硬币或纸币,选择想要的饮料,饮料就会在机器的下方滚出。大家有没有相关如果用程序去写一个饮料机要怎么样实现呢?

首先我们可以分享一下这部饮料机有几种状态

一、没有钱的状态

二、有钱的状态

三、售出的状态

四、销售一空的状态

好吧,知道了这些状态之后我们开始写代码了!

JuiceMachine.php

_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!
"; }elseif($this->_state == JuiceMachine::NOMONEY){ echo "you just insert a coin
"; $this->_state = JuiceMachine::HASMONEY; }elseif($this->_state == JuiceMachine::SOLD){ echo "wait a minute, we are giving you a bottle of juice
"; }elseif($this->_state == JuiceMachine::SOLDOUT){ echo "you can't insert coin, the machine is already soldout
"; } } /** * 退回硬币 */ public function retreatCoin(){ if($this->_state == JuiceMachine::HASMONEY ){ echo "coin return!
"; $this->_state = JuiceMachine::NOMONEY; }elseif($this->_state == JuiceMachine::NOMONEY){ echo "you have'nt inserted a coin yet
"; }elseif($this->_state == JuiceMachine::SOLD){ echo "sorry, you already clicked the botton
"; }elseif($this->_state == JuiceMachine::SOLDOUT){ echo "you have'nt inserted a coin yet
"; } } /** * 点击饮料对应的按钮 */ public function clickButton(){ if($this->_state == JuiceMachine::HASMONEY ){ echo "you clicked, we are giving you a bottle of juice...
"; $this->_state = JuiceMachine::SOLD; //改变饮料机的状态为售出模式 $this->dispend(); }elseif($this->_state == JuiceMachine::NOMONEY){ echo "you clicked,but you hav'nt inserted a coin yet
"; }elseif($this->_state == JuiceMachine::SOLD){ echo "click twice does'nt get you two bottle of juice
"; }elseif($this->_state == JuiceMachine::SOLDOUT){ echo "you clicked, but the machine is already soldout
"; } } /** * 发放饮料 */ public function dispend(){ if($this->_state == JuiceMachine::HASMONEY ){ echo "please click the button first
"; }elseif($this->_state == JuiceMachine::NOMONEY){ echo "you need to pay first
"; }elseif($this->_state == JuiceMachine::SOLD){ echo "now you get you juice
"; //饮料机中的饮料数量减一 $this->_count--; if($this->_count <= 0){ echo "opps, runing out of juice
"; //如果这时饮料机中没有饮料了,将饮料机的状态重置为销售一空 $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
"; } } }

index.php

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

NomoneyState.php

_juiceMachine = $juiceMachine; } /* (non-PHPdoc) * @see State::insertCoin() */ public function insertCoin() { // TODO Auto-generated method stub echo "you just insert a coin
"; //将饮料机的状态切换成有钱的状态 $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
"; } /* (non-PHPdoc) * @see State::clickButton() */ public function clickButton() { // TODO Auto-generated method stub echo "you clicked,but you hav'nt inserted a coin yet
"; } /* (non-PHPdoc) * @see State::dispend() */ public function dispend() { // TODO Auto-generated method stub echo "you need to pay first
"; } }

HasmoneyState.php

_juiceMachine = $juiceMachine; } /* * (non-PHPdoc) @see State::insertCoin() */ public function insertCoin() { // TODO Auto-generated method stub echo "you can't insert another coin!
"; } /* * (non-PHPdoc) @see State::retreatCoin() */ public function retreatCoin() { // TODO Auto-generated method stub echo "coin return!
"; $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...
"; // 改变饮料机的状态为售出模式 $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
"; } }

SoldoutState.php

_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
"; } /* (non-PHPdoc) * @see State::retreatCoin() */ public function retreatCoin() { // TODO Auto-generated method stub echo "you have'nt inserted a coin yet
"; } /* (non-PHPdoc) * @see State::clickButton() */ public function clickButton() { // TODO Auto-generated method stub echo "you clicked, but the machine is already soldout
"; } /* (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
"; } }

SoldState.php

_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
"; } /* (non-PHPdoc) * @see State::retreatCoin() */ public function retreatCoin() { // TODO Auto-generated method stub echo "sorry, you already clicked the botton
"; } /* (non-PHPdoc) * @see State::clickButton() */ public function clickButton() { // TODO Auto-generated method stub echo "click twice does'nt get you two bottle of juice
"; } /* (non-PHPdoc) * @see State::dispend() */ public function dispend() { $this->_juiceMachine->decJuice(); if($this->_juiceMachine->getCount() <= 0){ echo "opps, runing out of juice
"; //如果这时饮料机中没有饮料了,将饮料机的状态重置为销售一空 $this->_juiceMachine->setState($this->_juiceMachine->getSoldoutState()); }else{ //将饮料机的状态重置为没有钱 $this->_juiceMachine->setState($this->_juiceMachine->getNomoneyState()); } } }

WinnerState.php

_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
"; } /* * (non-PHPdoc) @see State::retreatCoin() */ public function retreatCoin() { // TODO Auto-generated method stub echo "sorry, you already clicked the botton
"; } /* * (non-PHPdoc) @see State::clickButton() */ public function clickButton() { // TODO Auto-generated method stub echo "click twice does'nt get you two bottle of juice
"; } /* * (non-PHPdoc) @see State::dispend() */ public function dispend() { echo "you are a winner! you get two bottle of juice!
"; $this->_juiceMachine->decJuice(); if ($this->_juiceMachine->getCount() > 0) { $this->_juiceMachine->decJuice(); if ($this->_juiceMachine->getCount() <= 0) { echo "opps, runing out of juice<

-六神源码网