设计模式专题(十二)——状态模式
设计模式专题(十二)——状态模式
(原创内容,转载请注明来源,谢谢)
一、概述
状态模式(State)是指当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。状态模式主要解决对象的状态转换表达式过于复杂的情况,把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
当状态的变化,会涉及很多的步骤,则用状态模式可以让流程更清晰,并更利于维护。
状态模式的优点,在于将内部的复杂局部状态变化分割出来,将复杂的状态行为分离出去。
状态模式和策略模式相似,是将不同的状态用不同的类进行分开,有一个统一的地方去调用。
但是不同之处在于,状态模式中各个状态是互相联系,且根据业务需要,执行完其中一个状态类后,通常需要执行下一个状态类。另外,状态模式的状态变化到下一个类这件事情,不是由总的类去控制,而是每个不同的状态类会自动根据条件去通知其他状态类。
而策略模式,更注重于依赖注入,由一个总的类去判断状态后,去选择调用不同的类。
状态模式的行为是平行性,不可相互替换的;而策略模式的行为是平等的,是可以相互替换的。
二、类图
三、业务场景
1)业务分析
以购物订单为例,有支付状态、发货状态、退货状态、退款状态等状态,状态之间互相有联系:
1、每种状态的变化都会对其他状态有所限制或允许,按照业务场景,以【支付状态-发货状态/退货状态-退款状态】作为区分,支付状态是前提条件,发货状态和退货状态并行。
2、支付状态有待支付、已支付,待支付时其他状态都为不允许;为已支付时,发货状态分为已发货、未发货、无货;退货状态为没有退货申请、有退货申请。
3、发货状态分为待发货、已发货、确认收货、退货申请,如果是待发货的情况下,收到退货申请,则直接审批通过、退货成功,进入退货状态;如果已发货,则由商家决定允许退货、不允许退货。另外,发货状态还有确认收货的状态,此时不允许退货;而如果已经发退货申请,则不允许确认收货。
4、退货状态分为直接退货(由于未发货)、等待商家审批、允许退货、不允许退货。直接退货和允许退货则影响到退款状态为开始退款,不允许退货则返回支付状态为退款失败,等待审批状态为挂起。退货成功时不允许确认收货。
5、退款状态为开始退款、退款成功两种状态。
2)功能分析
1、客户端的类Shopping,可以支付、退款申请、确认收货。
2、状态基类,支付、退款申请调用支付类,确认收货调用收货类。再由这两个类去调用其它的类进行操作。
3、状态类的子类,包括支付类、发货类、退货类、退款类,共四个类。
3)PHP实现
由于几个子类相似,仅实现支付类和发货类两个子类。
//订单实体
class Order{
public $payState;//支付状态
public$deliveryState;//发货状态
public $returnState;//退货状态
public $refundState;//退款状态
}
//客户端类
class Shopping{
//....先行进行各类操作验证,确认有操作权限后
private $order;
private $stateBase;
public function__construct(Order $order){
$this->order= $order;
$this->stateBase= new StateBase($order);
}
public function pay(){
return$this->stateBase->pay();
}
public functionrefund(){
return$this->stateBase->refund();
}
public functionconfirmRecipt(){
return$this->stateBase->confirmRecipt();
}
}
//状态基类
abstract class StateBase{
private $order;
public function__construct(Order $order){
$this->order= $order;
}
public function pay(){
return newStatePay($this->order, 'pay');
}
public functionrefund(){
return newStatePay($this->order, 'refund');
}
public functionconfirmRecipt(){
return newStatePay($this->order, 'confirm');
}
}
//支付类
class StatePay extends StateBase{
private $order;
public static constNOT_PAY = 0;
public static constHAS_PAY = 1;
public function__construct(Order $order, $func){
$this->order= $order;
if(method_exists($this,$func)){
return$this->$func;
}else{
returnfalse;
}
}
//支付
public function pay(){
if(self::HAS_PAY== $this->order->payState){
echo'已支付,不用重复支付';
returnfalse;
}
$this->order->payState= self::HAS_PAY;
return newStateGoods($this->order, 'send');
}
//退款后状态置于未支付
public functionsetNotPay(){
$this->order->payState= self::NOT_PAY;
return$this->order;
}
}
//发货类
class StateGoods extends StateBase{
private $order;
public static constNOT_SEND = 0;
public static constHAS_SEND = 1;
public static constHAS_RECEIVE = 2;
public static constAPPLY_RETURN = 3;
public function__construct(Order $order, $func){
$this->order= $order;
if(method_exists($this,$func)){
return$this->$func;
}else{
returnfalse;
}
}
//发货
public functionsend(){
if(StatePay::HAS_PAY!= $this->order->payState){
echo'请先付款';
returnfalse;
}
if(self::NOT_SEND!= $this->order->payState){
echo'不在未发货状态,不能发货';
returnfalse;
}
}
}
——written by linhxx 2017.08.09
相关阅读:
设计模式专题(十一)——抽象工厂模式
设计模式专题(十)——观察者模式
设计模式专题(九) ——外观模式
设计模式专题(八) ——模板方法模式
设计模式专题(七)——建造者模式
设计模式专题(六)——原型模式
设计模式专题(五)——工厂方法模式
设计模式专题(四)——代理模式
设计模式专题(三)——装饰模式
设计模式专题(二)——策略模式
设计模式专题(一)——面向对象的设计原则
- 基于AOE网的关键路径的求解
- 【LeetCode 122】关关刷题日记25-Best Time to Buy and Sell Stock II
- 【干货】python正则表达式应用笔记
- .NET跨平台之旅:将示例站点从 ASP.NET 5 RC1 升级至 ASP.NET Core 1.0
- .NET跨平台之旅:在Linux上以本地机器码(native)运行ASP.NET Core站点
- 【干货】基于pytorch的CNN、LSTM神经网络模型调参小结
- jenkins配置.net mvc网站
- 简述【聚类算法】
- word2vec理论与实践
- GMP大法教你重新做人(从入门到实战)
- Highway Networks
- CTF---编程入门第一题 循环
- Z.ExtensionMethods 一个强大的开源扩展库
- 【干货】神经网络SRU
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- JS(jQuery)实现聊天接收到消息语言自动提醒功能详解【提示“您有新的消息请注意查收”】
- OpenCV4.1.0+VS2017环境配置的方法步骤
- 详解如何实现Laravel的服务容器的方法示例
- laravel 数据迁移与 Eloquent ORM的实现方法
- PDO::query讲解
- Laravel5框架自定义错误页面配置操作示例
- PHP-FPM和Nginx的通信机制详解
- PHP PDOStatement::columnCount讲解
- PHP中上传文件打印错误错误类型分析
- Laravel如何创建服务器提供者实例代码
- PDO::quote讲解
- php intval函数用法总结
- Python Selenium模块安装使用教程详解
- Python selenium模块实现定位过程解析
- Django ORM判断查询结果是否为空,判断django中的orm为空实例