内容简介:你是否经常请(】。在这不同的状态是可以有不同的操作的。
一、定义
你是否经常请( 偷 )假( 懒 )?是不是对公司万恶的请假申请流程深 恶 痛绝 。有没有想过偷偷改造这个万恶的系统,从 申请->项目经理审批->部门审批->老板审批->完成 偷偷改为 申请->完成。为了实现这个正义[ 偷笑 ]又合理的诉求,你得先学会今天要介绍的设计模式,因为你们公司的这个流程可能就是用今天这个模式设计的。来看看这个 设计模式 是怎么来抽象这类流程性的业务的。
状态模式【百度百科】 :当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
这个定义看起来莫名其妙,咋一看,我也不知道它要表达什么。个人的理解:某个对象是有状态的,比如我们上面的请假流程,它处于项目经理状态,那项目经理可以审核你的请假申请,到了老板处理环节,老板直接把你申请单删了【 哈哈】。在这不同的状态是可以有不同的操作的。
不知道你看懂了定义了没??什么?没看懂,那就直接看下面的代码咯,talk is cheap show me the code。
二、UML图
UML图如下,我直接把请假这个例子画了个UML图,如下,有一个 公共的State抽象类 ,里面定义了两个变量来保存当前状态的状态Code,状态Name,下面为 具体的状态 ,分别为:AppState(申请状态),ProjectManagesState(项目经理审核状态),BossState(老板审核状态),通过Context来提供给客户端使用。
三、请假流程实现
具体代码实现如下:
1、状态抽象类
package com.design.state; public abstract class State { private String stateCode; private String stateName; //往下个环节走 public abstract void toNextState(Context context); public State(String stateCode, String stateName){ this.stateCode = stateCode; this.stateName = stateName; } public String getStateCode() { return stateCode; } public void setStateCode(String stateCode) { this.stateCode = stateCode; } public String getStateName() { return stateName; } public void setStateName(String stateName) { this.stateName = stateName; } } 复制代码
2、定义具体的状态
package com.design.state; /** * 申请状态 */ public class AppState extends State{ public AppState(){ super("Apply", "申请环节"); } @Override public void toNextState(Context context) { //申请状态,这里可以做该状态下的操作 System.out.println("我是申请人,我申请休假,下一个环节是项目经理审核!!"); //直接进去项目经理审核状态 context.setCurrentState(new ProjectManagesState()); } } 复制代码
package com.design.state; /** * 项目经理审核状态 */ public class ProjectManagesState extends State{ public ProjectManagesState(){ super("ProjectManages", "项目经理审核环节"); } @Override public void toNextState(Context context) { //项目经理审核状态,这里可以做该状态下的操做 System.out.println("我是项目经理,那臭小子一定有跑去面试了,哎,帮他一把,同意了,下个环节让老板审去"); //直接进去老板审核状态 context.setCurrentState(new BossState()); } } 复制代码
package com.design.state; /** * 老板审核状态 */ public class BossState extends State{ public BossState(){ super("Boss Audit", "老板审核环节"); } @Override public void toNextState(Context context) { //项目经理审核状态,这里可以做该状态下的操做 System.out.println("我是老板,我同意你请假了!!!流程结束!"); } } 复制代码
3、上下文类
package com.design.state; public class Context { private State currentState; public Context(State state){ currentState = state; } public void toNextState(){ currentState.toNextState(this); }; public State getCurrentState() { return currentState; } public void setCurrentState(State currentState) { this.currentState = currentState; } } 复制代码
4、写好了,看下怎么调用
package com.design.state; public class TestMain { public static void main(String[] args) { //创建申请休假单 Context context = new Context(new AppState()); System.out.println("状态:"+context.getCurrentState().getStateName()); //提交申请 context.toNextState(); System.out.println("状态:"+context.getCurrentState().getStateName()); //项目经理审核 context.toNextState(); System.out.println("状态:"+context.getCurrentState().getStateName()); //老板审核 context.toNextState(); } }复制代码
5、执行结果
五、优缺点
1、优点
(1)、将与特定状态相关的行为局部化,将不同状态的行为分割开来。
(2)、把状态转移逻辑分布到具体状态类中,减少相互间的依赖。
看不懂这两个优点??OK,我们来解释下,先来看看,不用状态模式,我们代码会怎么写?
package com.design.state; public class StateChange { private int state = 0; private final static int APPLY=0; //申请状态 private final static int PROJECTMANAGES=1;//项目经理审核状态 private final static int BOSS=2;//老板审核状态 private final static int FINISH=3;//流程结束状态 public void toNextState(){ switch (state){ case 0: //申请状态,做点操作 System.out.println("写申请书!!!"); //进入项目经理审核状态 state = PROJECTMANAGES; break; case 1: System.out.println("项目经理审核,同意你申请了"); //进入老板审核状态 state = BOSS; break; case 2: System.out.println("我是老板,同意你申请了"); //进入结束状态 state = FINISH; break; default: break; } } }复制代码
你是不是写的跟我一样呢??有没有注意到,所有的操作,无论是哪个状态的操作都是在这个类中完成的,而使用状态模式,不同状态下的行为是定义在不同的状态类下的。这就是前面说的优点1。
我们状态切换是通过switch来判断状态,再决定下一个状态的,而在状态模式下,切换到下一个状态,是在具体的状态类下进行的,可以减少if之类的判断逻辑。这就是优点2。
2、缺点
(1)、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
(2)、状态模式对"开闭原则"的支持并不太好,新增状态时,不仅得增加状态类,还得修改原来已经有的状态,让之前的状态切换到新增的状态。
六、总结说明
状态模式将原来通过判断实现的状态切换分散到各具体状态类中,比如上面切换到“老板审核状态”,是在“项目经理审核状态”中进行的,当状态比较多的情况,不容易理清各状态切换关系。同时它有将各状态的操作独立到状态类中,方便测试,还有分隔开各不同操作,便于阅读代码。实际运用中可根据自己的场景进行权衡。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 设计模式——订阅模式(观察者模式)
- 设计模式-简单工厂、工厂方法模式、抽象工厂模式
- java23种设计模式-门面模式(外观模式)
- 设计模式-享元设计模式
- Java 设计模式之工厂方法模式与抽象工厂模式
- JAVA设计模式之模板方法模式和建造者模式
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C++Primer Plus
Stephen Prata、孙建春、韦强 / 孙建春、韦强 / 人民邮电出版社 / 2005-5 / 72.00元
C++ Primer Plus(第五版)中文版,ISBN:9787115134165,作者:(美)Stephen Prata著;孙建春,韦强译一起来看看 《C++Primer Plus》 这本书的介绍吧!