前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PHP设计模式入门之状态模式原理与实现方法分析

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

作者头像
砸漏
发布2020-11-02 15:24:17
3350
发布2020-11-02 15:24:17
举报
文章被收录于专栏:恩蓝脚本

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

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

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

一、没有钱的状态

二、有钱的状态

三、售出的状态

四、销售一空的状态

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

JuiceMachine.php

代码语言:javascript
复制
<?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

代码语言:javascript
复制
<?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

代码语言:javascript
复制
<?php
interface State{
/**
* 插入硬币
*/
public function insertCoin();
/**
* 回退硬币
*/
public function retreatCoin();
/**
* 点击按钮
*/
public function clickButton();
/**
* 发放饮料
*/
public function dispend();
}

NomoneyState.php

代码语言:javascript
复制
<?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

代码语言:javascript
复制
<?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

代码语言:javascript
复制
<?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

代码语言:javascript
复制
<?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

代码语言:javascript
复制
<?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

代码语言:javascript
复制
<?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

代码语言:javascript
复制
<?php
require_once 'JuiceMachine.php';
$juiceMachine = new JuiceMachine(2);
$juiceMachine- insertCoin();
$juiceMachine- clickButton();

更多关于PHP相关内容感兴趣的读者可查看本站专题:《php面向对象程序设计入门教程》、《PHP数组(Array)操作技巧大全》、《PHP基本语法入门教程》、《PHP运算与运算符用法总结》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

希望本文所述对大家PHP程序设计有所帮助。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-09-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档