0、前言
软件系统一般由一些基础模块组成,每个模块负责一项具体的功能。软件系统运行时,就是按照一定的规则运行不同的模块,模块之间的执行顺序多种多样,比如串行、并行、条件判断、以及复杂逻辑树。对于一个小的软件,这些执行逻辑可以直接在代码中写死,但对于一个超大型的软件系统,必须引入『编排机制』来定义这些执行逻辑。
1、串行
串行任务的处理很简单,能够直接像平常同样编写代码:
Func1(); // Action1 的执行逻辑
Func2(); // Action2 的执行逻辑
2、并发
Action1 执行完之后,Action2、Action3、Action3 可以并发执行,它们之间没有顺序要求,实现上可以启 3 个子线程就可以了。
3、条件
Action1 执行完之后,根据返回结果判断是执行 Action2 还是 Action3.
result = Func1();
if (result 满足 条件A) {
Func2();
} else if (result 满足 条件B) {
Func(2);
}
4、复杂逻辑树
若是条件简单,则无所谓,可是若是有多层的逻辑嵌套。最后造成一个逻辑树,那么咱们就会在条件逻辑中迷失,对将来的开发维护形成极大的成本损耗。像上述这种结构,那么该怎么编排这个复杂的逻辑呢?
4.1、普通状态机
首先定义一个程序运行状态和执行函数的映射表:
StateMap = {
"state1": Func1;
"state2": Func2;
"state3": Func3;
}
StateMap 中记录所有状态及对应的执行任务,那么如何指定状态之间的关系呢?最简单的处理方式就是:咱们可以让每个状态的任务返回下一个状态,若是没有返回状态,就表明完结了。
while(true) {
if ("state1") {
next_state = Func1();
} else if ("state2") {
next_state = Func2();
} else if ("state3") {
next_state = Func3();
}
}
上述代码是一个最简单的状态机实现,它有如下三个问题:
没法将当前函数的执行结果传递给下一个状态。
在当前执行的函数内部必须人为知道下一个状态是什么。
将对逻辑的判断封装到任务函数中,对于整个逻辑的表达没有帮助,或者相比于以前,反却是绕了一圈,更乱了,并没有做到真正地解耦。
4.2、状态带出返回结果
这个很好处理,维护一个全局的上下文即可。
while(true) {
if ("state1") {
next_state = Func1(context);
} else if ("state2") {
next_state = Func2(context);
} else if ("state3") {
next_state = Func3(context);
}
}
4.3、抽象出状态转换器
上述问题2和问题3的解决方案就是将对状态的判断独立出来,任务只负责处理任务自身的逻辑,对于状态的判断交由『状态转换器』来完成:『任务转换器』能够直接根据配置或者根据上一个任务的执行结果来决定下一个状态,和具体任务无关。
while(true) {
if ("state1") {
Func1(context);
next_state = StateConvert(context);
} else if ("state2") {
next_state = Func2(context);
next_state = StateConvert(context);
} else if ("state3") {
next_state = Func3(context);
next_state = StateConvert(context);
}
}
5、总结
编排多任务的目的就是使得代码逻辑看起来更清晰,减少模块间的耦合,各模块间的调用逻辑变得可以灵活组合。