设计模式-State(状态模式)
状态模式-事物的状态
定义:状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
直接上例子好了
<?php
/**
*状态模式-事物的状态
定义:状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
就按照糖果机的例子,自动售卖机的例子 分别有 正常销售,售罄,没有投入硬币,投入硬币 四个状态
*/
interface State{
public function insertQuater(); //塞入硬币
public function ejectQuater(); //弹出硬币
public function turnCrank();//拉动曲柄
public function dispense(); //出货
}
/**
*
*@desc 没有投入硬币的状态
*/
class NoQuarterState implements State{
public $gumballMachine;
public function __construct(GumballMachine &$gumballMachine){
$this->gumballMachine = $gumballMachine;
}
public function insertQuater(){
echo "You insert a quarter \r\n";
$this->gumballMachine->setState($this->gumballMachine->getHasQuarterState());
}
public function ejectQuater(){
echo "You haven't inserted a quarter \r\n";
}
public function turnCrank(){
echo "You turned,but there is no quarter \r\n";
}
public function dispense(){
echo "You need to pay first \r\n";
}
}
/**
* @desc 已经投入硬币了
*/
class HasQuarterState implements State{
public $gumballMachine;
public function __construct(GumballMachine &$gumballMachine){
$this->gumballMachine = $gumballMachine;
}
public function insertQuater(){
echo "You cant't insert another quarter! \r\n";
}
public function ejectQuater(){
echo "Quarter returned \r\n";
$this->gumballMachine->setState($this->gumballMachine->getNoQuarterState());
}
public function turnCrank(){
echo "You turned \r\n";
if( (rand(1,2) == 1) && ($this->gumballMachine->getCount() > 1) ){ //如果是幸运玩家 并且有足够的球 这里是两颗 就进入幸运状态 否则就正常售卖 这个随便概率了
$this->gumballMachine->setState($this->gumballMachine->getWinnerState());
} else {
$this->gumballMachine->setState($this->gumballMachine->getSoldState());
}
}
public function dispense(){
echo "No gumball dispensed \r\n";
}
}
/**
* @desc 售卖中
*/
class SoldState implements State{
public $gumballMachine;
public function __construct(GumballMachine &$gumballMachine){
$this->gumballMachine = $gumballMachine;
}
public function insertQuater(){
echo "Please wait,we're already giving you a gumball \r\n";
}
public function ejectQuater(){
echo "Sorry ,you already turned the crank \r\n";
}
public function turnCrank(){
echo " Turning twice doesn't get you another gumball !\r\n";
}
public function dispense(){ //出货
$this->gumballMachine->releaseBall();
if($this->gumballMachine->getCount() > 0){ //如果还有存货
$this->gumballMachine->setState($this->gumballMachine->getNoQuarterState());
} else { //如果没有存货了
$this->gumballMachine->setState($this->gumballMachine->getSoldOutState());
}
}
}
/**
* @desc 售罄状况
*/
class SoldOutState implements State{
public $gumballMachine;
public function __construct(GumballMachine &$gumballMachine){
$this->gumballMachine = $gumballMachine;
}
public function insertQuater(){
echo "You can't insert a quarter,the mechine is sold out!\r\n";
}
public function ejectQuater(){
echo "You haven't inserted a quarter \r\n";
}
public function turnCrank(){
echo "You turned,but there is no quarter \r\n";
}
public function dispense(){
echo "No gumball dispensed \r\n";
}
}
/**
* @desc 特殊情况 有概率发放两个球
*/
class WinnerState implements State{
public $gumballMachine;
public function __construct(GumballMachine &$gumballMachine){
$this->gumballMachine = $gumballMachine;
}
public function insertQuater(){
echo "Please wait,we're already giving you a gumball \r\n";
}
public function ejectQuater(){
echo "Sorry ,you already turned the crank \r\n";
}
public function turnCrank(){
echo " Turning twice doesn't get you another gumball !\r\n";
}
public function dispense(){ //出货
echo " You're a winner!You get two gumballs for your quarter!\r\n";
$this->gumballMachine->releaseBall(); //出球
if($this->gumballMachine->getCount() > 0){ //如果还有存货
$this->gumballMachine->releaseBall(); //再出出球
if($this->gumballMachine->getCount() > 0){ //如果还有存货
$this->gumballMachine->setState($this->gumballMachine->getNoQuarterState());
} else { //如果没有存货了
$this->gumballMachine->setState($this->gumballMachine->getSoldOutState());
}
} else { //如果没有存货了
$this->gumballMachine->setState($this->gumballMachine->getSoldOutState());
}
}
}
/**
*
* @desc 糖果机
*
*/
class GumballMachine{
public $soldOutState; //售罄状态
public $noQuarterState; //未投币状态
public $hasQuarterState; //已经投币状态
public $soldState; //售卖中状态
public $winnerState;// 中奖状态
public $state; //保存各个状态的状态值
public $count = 0; //当前数量
public function __construct($count){
$this->soldOutState = new SoldOutState($this);
$this->noQuarterState = new NoQuarterState($this);
$this->hasQuarterState = new HasQuarterState($this);
$this->soldState = new SoldState($this);
$this->winnerState = new WinnerState($this);
$this->count = $count;
if($count > 0){
$this->state = $this->noQuarterState;
}
}
public function insertQuater(){
//塞入硬币
$this->state->insertQuater();
}
public function ejectQuater(){
$this->state->ejectQuater();
}
public function turnCrank(){
$this->state->turnCrank();
$this->state->dispense();
}
public function setState($state){
$this->state = $state;
}
public function releaseBall(){ //出库操作
echo "A gumball commes rolling out the slot ...\r\n";
if($this->count != 0){
$this->count = $this->count - 1;
}
}
public function getSoldOutState(){
return $this->soldOutState;
}
public function getNoQuarterState(){
return $this->noQuarterState;
}
public function getHasQuarterState(){
return $this->hasQuarterState;
}
public function getSoldState(){
return $this->soldState;
}
public function getWinnerState(){
return $this->winnerState;
}
public function getCount(){
return $this->count;
}
}
//实例一个存货100的糖果机器 进行1000次随机操作
$gumballMachine = new GumballMachine(10);
$i=100;
while($i>0){
$action = rand(1,3);
if($action == 1){
$gumballMachine->insertQuater(); //投硬币
}elseif($action == 2){
$gumballMachine->ejectQuater(); //退硬币
}elseif($action == 3){
$gumballMachine->turnCrank(); //拉杆
}
$i--;
}
