行为型设计模式的一种

【DP】定义

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

使用场景

一个对象在多个状态下行为不同,且这些状态可以互相转换

类图

状态模式

该类图的核心是: 状态管理类和状态接口的聚合关系,以及状态类方法的参数是状态管理类。

举例

假设单据审批过程的状态包括: 未提交、未审核、已完成三个状态,处于每个状态的单据都需要有不同的处理,具体如下:

  1. 未提交状态的处理是提交,并切换到未审核状态;
  2. 未审核状态的处理是审核,并切换到已完成状态;
  3. 已完成状态的处理是打印单据。

按照状态模式首先定义状态接口和实现类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**
* 状态管理类
*/
public class Context {
private State state;

public Context() {
// 初始状态为未提交
this.state = new UnCommit();
}

public void setState(State state) {
this.state = state;
}
// 外部请求
public void request() {
state.handle(this);
}
}
/**
* 状态接口
*/
public interface State {
void handle(Context context);
}
/**
* 未提交
*/
public class UnCommit implements State {
@Override
public void handle(Context context) {
// 做提交
doSomethingToCommit();
// 修改状态
context.setState(new UnApprove());
}
}
/**
* 未审核
*/
public class UnApprove implements State {
@Override
public void handle(Context context) {
// 做审核
doSomethingToApprove();
// 修改状态
context.setState(new Complete());
}
}
/**
* 已完成
*/
public class Complete implements State {
@Override
public void handle(Context context) {
// 打印单据
doSomethingToPrint();
}
}

客户端处理如下:

1
2
3
4
5
6
7
8
9
10
11
12
public class Main {    
public static void main() {
// 创建状态管理类,并初始为未提交状态
Context context = new Context();
// 第一次请求,执行提交,状态变为未审核状态
context.request();
// 第二次请求,执行审核,状态变为已完成状态
context.request();
// 第三次请求,执行打印
context.request();
}
}

可以看到,客户端在调用时不需要担心当前状态是什么,只需要依次执行请求即可,每个状态有自己的处理和状态切换。

注意事项

  1. 与策略模式的对比:二者虽然都是行为模式,且类图很像,都是让客户端透明的执行算法策略或者状态操作,但是策略模式是封装了算法的变化,各个算法类之间没有关系,而状态模式是封装了状态的变化,各个状态之间可以转换。