状态模式主要解决当控制一个对象状态的转换的条件表达过于复杂的情况,使得状态的转换不依赖于整体的操作。本文将通过一个具体的例子说明状态模式的应用。假设下面一个场景:
一个新任务提交后,先是收集数据,数据收集完成后等等分配一台机器,分配到机器后就可以将此任务部署至此机器后就可以通知相关模块开始工作。
先对此场景做分析如下:
一个任务共分四个步骤:一收集数据,二分配机器,三部署到测试机,四通知相关对象。
任务的状态可以分为:new, waiting, Ready, Running分别对应新任务提交,等待分配机器,准备部署,和部署完成于上面的步骤一一对应。
定义一个任务类:
// 这里是分别为以上四个步骤定义的接口
2: {
3:
// 任务在数据库里对应的ID
string taskIdInDataTable;
string TaskIdInDataTable
7: {
8: get
9: {
return taskIdInDataTable;
11: }
12: set
13: {
value;
15: }
16: }
17:
// 任务的状态
19:
private TaskState _TaskState;
public TaskState TaskState
22: {
23: get
24: {
return _TaskState;
26: }
27:
28: set
29: {
value;
+ _TaskState.GetType().Name);
32: }
33: }
34:
public Task()
36: {
new NewTaskState();
38: }
39:
// 可以指定一个任务的当前状态
41:
public UpDateTask(TaskState taskTask)
43: {
this._TaskState = taskTask;
45: }
46:
/// <summary> 改变一个任务的状态至当前任务的下一个状态
/// </summary>
void ChangeState()
50: {
51: System.Threading.Thread.Sleep(500);
this);
53: }
54:
/// 以下是实现接口中的方法
/// 合并数据
bool gatherData()
58: {
59:
true;
61: }
62:
/// 分配机器
/// 分配机器放在基类里面做,因为这个动作对每个任务来说基本都是一样的
bool allotMachine()
66: {
new DoWork();
68:
this.taskIdInDataTable);
70: }
71:
72:
/// 部署至测试机
/// 部署至测试机放在基类里面做,因为这个动作对每个任务来说基本都是一样的
bool deployTestManchine()
76: {
new DoWork();
78:
this.taskIdInDataTable);
80: }
81:
/// 通知相关人员
83:
/// 通知相关人员放在基类里面做,因为这个动作对每个任务来说基本都是一样的
bool deployTestManchine()
86: {
new DoWork();
88:
this.taskIdInDataTable);
90: }
91:
92: }
93:
94: 此我们的任务类已经定义完成,其中有一个ChangeState的方法,此方法负责调用状态类的改变状态的方法。
95:
96: 下面就写Status类:
97:
98: 是定义一个超类,此类只有一个方法就是ChangeState, 此方法负责控制任务状态的转换。
99:
class TaskState
101: {
/// <summary>状态改变过程
/// </summary>状态的改变由统一的接口进行从一个状态到下一下状态的改变,
/// 使用时不用关心内部的状态是怎么改变的,只需统一调用此方法即可。
void ChangeState(UpDateTask task);
107: }
108:
109: 面定义具体的状态类:
110:
111: / 新任务状态
class NewTaskState: TaskState
113: {
void ChangeState(UpDateTask task)
115: {
// 检查当前状态
this == task.TaskState)
118: {
if (task.gatherData())
120: {
new WaitingTaskState(task);
122: }
// 如果合并数据任务失败,将任务打到已清除状态
124: {
new DeletedState(task);
126: }
127: }
128: }
129:
public NewTaskState()
131: {
132:
133: }
134:
public NewTaskState(UpDateTask task)
136: {
137: DoWork.setTaskState(task.TaskIdInDataTable, enumTaskState.NewTask);
138: }
139: }
140:
// 等待任务状态
class WaitingTaskState : TaskState
143: {
void ChangeState(UpDateTask task)
145: {
this == task.TaskState)
147: {
if (task.allotMachine())
149: {
new ReadyTaskState(task);
151: }
else
153: {
new WaitingTaskState(task);
155: }
156: }
157: }
158:
public WaitingTaskState()
160: {
161:
162: }
163:
public WaitingTaskState(UpDateTask task)
165: {
166: DoWork.setTaskState(task.TaskIdInDataTable, enumTaskState.Waiting);
167: }
168:
169: }
170:
// 准备任务状态
class ReadyTaskState : TaskState
173: {
void ChangeState(UpDateTask task)
175: {
this == task.TaskState)
177: {
if (task.deployTestManchine())
179: {
new RunningState(task);
181: }
else
183: {
// 部署失败则重新分配新的测试机器
new WaitingTaskState(task);
186: }
187: }
188: }
189:
190:
public ReadyTaskState()
192: {
193:
194: }
195:
public ReadyTaskState(UpDateTask task)
197: {
198: DoWork.setTaskState(task.TaskIdInDataTable, enumTaskState.Ready);
199: }
200:
201:
202: }
203:
// 运行任务状态
class RunningState : TaskState
206: {
void ChangeState(UpDateTask task)
208: {
// send e-mail
210:
211: }
212:
213:
public RunningState()
215: {
216:
217: }
218:
public RunningState(UpDateTask task)
220: {
221: DoWork.setTaskState(task.TaskIdInDataTable, enumTaskState.Running);
222: }
223: }
224:
// 下来看客户端调用
226:
new Task ();
228:
// 为此任务指定一个ID
230:
231: 来就最重要的,做了这么多事就是为了下面的调用:
232:
233: ask.ChangeState();
234:
235: ask.ChangeState();
236:
237: ask.ChangeState();
238:
239: ask.ChangeState();