状态模式的应用

前景:

     xx公司要启动一个项目,这个项目的需求是合同协议管理,需求分别为:

      1.  合作的过程中创建一份协议。

      2.  协议开始的过程中可以暂停和恢复。

      3.  当然合作可以延长合作时间和提前结束,不管哪一种都要算服务天数,因为费用是按天计算的。

      4.  财务可以看到本月实际的营业额。

    接到需求之后就有人开始编码了(这是国内的习惯):

     协议创建的时候的合法性检测:

#检测是否存在合作中的协议
.....
$isCooperation = Agreement::model()->exists("nick=? and begin_date>=? and end_date<=?",array('xx',date(),date()));
if($isCooperation){
     throw new Exception("存在合作中的协议,无法新建");    
}

#检测是否有暂停的协议
$isExistsStop =  Agreement::model()->exists("nick=? and status=?",array('xx','stop'));

if($isExistsStop){
      throw new Exception("存在暂停的协议,无法新建");    
}

......

  协议开始的时候的合法性检测:

#检测是否存在为开始状态的协议
$agreement = Agreement::model()->find("nick=? and status=? begin_date>=? and end_date<=?",array('xx','NotStart',date(),date()));

if($agreement == null){
     throw new Exception("未找到开始状态的订单");
}

$agreement->start_date = date();
$agreement->status = 'Start';
$agreement->save(); 
......

  协议暂停的时候的合法性检测:

#同上

  

  状态越来越多 的时候,我们就越来越麻木了,不知道当前的动作会转变成什么状态,前置状态是否合理。

解决这一问题,我们引进下设计模式这个概念,其实代码基础还是不会变,只是转成了另外一种表现形式。 

状态模式解读:http://www.cnblogs.com/wangjq/archive/2012/07/16/2593485.html

1. 概述

  当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

2. 解决的问题

  主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同的一系列类当中,可以把复杂的逻辑判断简单化。

3. 模式中的角色

  3.1 上下文环境(Context):它定义了客户程序需要的接口并维护一个具体状态角色的实例,将与状态相关的操作委托给当前的Concrete State对象来处理。

  3.2 抽象状态(State):定义一个接口以封装使用上下文环境的的一个特定状态相关的行为。

  3.3 具体状态(Concrete State):实现抽象状态定义的接口。

 

我们从需求中分析下,提出动词:

1. 开始 (Start)

2. 暂停 (Pause)

3. 恢复 (Resume)

4. 终止 (Over)

5. 续约 (Review)

根据状态,我们列出以下状态:

1. 未开始(NotStart)

2. 服务中 (Start)

3. 暂停服务 (Pause)

4. 服务结束 (Over)

 

我们在来列一份表格

   未开始    服务中    暂停服务    服务结束  
  开始    服务中  error  error    error
  暂停  error  暂停服务  error  error
  恢复  error  error  服务中  error
  终止     服务结束  服务结束  服务结束  服务结束
  续约  未开始  服务中  error  未开始/服务中  

这份表格代表着状态的转化过程。

我们根据状态模式的定义来化出类图结构:

 

代码如下(仅供参考):

<?php

class AgreementContext {

	/**
	* @var AgreementState
	*/
	private $state;

	public $agreement;	


	public function setState($state){
		$this->state = $state;
	}

	public function start(){
		$this->state->start($this);
	}

	public function pause(){
		$this->state->pause($this);
	}

	public function resume(){
		$this->state->resume($this);
	}

	public function over(){
		$this->state->over($this);
	}

}

abstract class AgreementState {	

	public function start($context);	
	public function pause($context);
	public function resume($context);
	public function over($context);
} 

class AgreementNotStartState extends AgreementState {

	public function start($context){

		if($context->agreement->begin_time >= time() && $context->agreement->end_time<=time()){
			$context->agreement->startDate = date();
			$context->state = new AgreementServiceState();
		}
	}

	public function pause($context){
		throw new Exception("The state is no service ,can not switch to pause", 1);		
	}

	public function resume($context){
		throw new Exception("The state is no service ,can not switch to resume", 1);		
	}

	public function over($context){
		$context->agreement->overDate = date();
		$context->state = new AgreementOverState();
	}

}

class AgreementServiceState extends AgreementState {


	public function start($context){
		throw new Exception("...", 1);		
	}	
	
	public function pause($context){
		if($context->agreement->begin_time >= time() && $context->agreement->begin_time<=time()){
			$context->agreement->stopDate  = date();
			$context->state = new AgreementPauseState();
		}
	}

	public function resume($context){
		throw new Exception("...", 1);		
	}

	public function over($context){
		$context->agreement->overDate = date();
		$context->state = new AgreementOverState();
	}

}

class AgreementPauseState extends AgreementState {


	....

	public function resume($context){		
		$context->agreement->resumeDate = date();
		$context->state = new AgreementServiceState();			
	}

	public function over($context){
		$context->agreement->overDate = date();
		$context->state = new AgreementOverState();
	}
	....

}

class AgreementOverState extends AgreementState {
	...
}

  

转载于:https://www.cnblogs.com/oshine/p/3894150.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值