状态模式,是11种行为型模式之一。一个生存在流程整个周期的对象,因事件触发改变对象的状态进而影响对象的行为(流程的走向)。状态模式就是把对象的行为与状态进行封装,通过改变状态进而影响行为。
状态模式几个关键对象类型:
Context: 一个生存在流程整个周期的对象
State: 封装对象状态的抽象类(State)和具体实现类
本文以请假流程为例,如图:
首先找出所有状态
- 0-草稿
- 1-申请
- 2-主管同意
- 3-主管不同意
- 4-部门同意
- 5-部门不同意
- 6-人事备案
其次找出事件
- 0-创建草稿
- 1-提交申请
- 2-提交主管审批
- 3-提交部门审批
- 4-提交人事备案
先看看未使用状态模式实现:
//流程申请表单
class Form {
private int days; // 请假天数
private String type; //请假类型
private String reason; //原因
Form(int days,String type,String reason){
this.days = days;
this.type = type;
this.reason = reason;
}
//省略geter、seter方法
}
class Context {
private Form form;
int state = 1;
Context(Form form, State state) {
this.form = form;
this.state = state;
}
//省略geter、seter方法
}
//流程引擎
class WorkFlowEngine {
Context context;
WorkFlowEngine () {
this.context = new Context();
}
public void create(Form form) {
this.context.setForm(form);
this.context.setState(0);
}
public void submit() {
if (this.context.getState() == 0) {
this.context.setState(1)
}
if (this.context.getState() == 4) {
this.context.setState(6)
}
}
public void submit(int event) {
if (this.context.getState() == 1) {
if (event == 0)
this.context.setState(3)
else
this.context.setState(2)
} else if (this.context.getState() == 2) {
if (event == 0)
this.context.setState(5)
else
this.context.setState(4)
} else if (this.context.getState() == 3) {
if (event == 1)
this.context.setState(2)
} else if (this.context.getState() == 5) {
if (event == 0)
this.context.setState(3)
else
this.context.setState(2)
}
}
}
public class Client {
public static void main(String[] args) {
Form form = new Form(3,"病假","发烧了")
WorkFlowEngine engine = new WorkFlowEngine();
//0-创建草稿
engine.create(form);
//1-提交申请
engine.submit();
//2-提交主管审批
engine.submit(1);
//3-提交部门审批
engine.submit(1);
//4-提交人事备案
engine.submit();
}
}
WorkFlowEngine 有很多的if分支,当流程有变化时,需要修改WorkFlowEngine,不符合开闭原则。
状态模式实现:
//流程申请表单
class Form {
private int days; // 请假天数
private String type; //请假类型
private String reason; //原因
Form(int days,String type,String reason){
this.days = days;
this.type = type;
this.reason = reason;
}
//省略geter、seter方法
}
//定义状态抽象
interface State {
public void action(Context context);
public void action(Context context, int event);
}
//状态实现类
//草稿
class State0 implements State {
int state = 0;
public void action(Context context) {
context.setState(new State1());
}
public void action(Context context, int event) {
}
//省略geter、seter方法
}
//申请
class State1 implements State {
int state = 1;
public void action(Context context) {
}
public void action(Context context, int event) {
if (event = 0) //不同意
context.setState(new State3());
else
context.setState(new State2());
}
//省略geter、seter方法
}
//主管同意
class State2 implements State {
int state = 2;
public void action(Context context) {
}
public void action(Context context, int event) {
if (event = 0) //不同意
context.setState(new State5());
else
context.setState(new State4());
}
//省略geter、seter方法
}
//省略其他状态代码
class Context {
private Form form;
private State state; //状态改为状态对象
Context(Form form, State state) {
this.form = form;
this.state = state;
}
//省略geter、seter方法
}
//流程引擎
class WorkFlowEngine {
Context context;
WorkFlowEngine () {
this.context = new Context();
}
public void create(Form form) {
this.context.setForm(form);
this.context.setState(new State0());
}
public void submit() {
this.context.getState().action(this.context);
}
public void submit(int event) {
this.context.getState().action(this.context, event);
}
}
public class Client {
public static void main(String[] args) {
Form form = new Form(3,"病假","发烧了")
WorkFlowEngine engine = new WorkFlowEngine();
//0-创建草稿
engine.create(form);
//1-提交申请
engine.submit();
//2-提交主管审批
engine.submit(1);
//3-提交部门审批
engine.submit(1);
//4-提交人事备案
engine.submit();
}
}
使用状态模式之后,WorkFlowEngine与流程状态进行了解耦,流程的变化不再影响WorkFlowEngine,更符合开闭原则。WorkFlowEngine、State类职责更加单一也更符合单一职责原则。
职责链模式遵循的设计原则和思想:
- 单一职责原则:把状态有关的动作封装到单独的状态类中,解耦WorkFlowEngine与流程,让WorkFlowEngine与State职责单一;
- 开闭原则:添加状态,只需要添加一个状态类,修改与状态有关的状态,不需要修改WorkFlowEngine及Context;