UML状态机基础

什么是状态机?

状态机是一种行为模型,用于描述对象在其生命周期中可能经历的各种状态,以及在这些状态之间的转换。在UML中,状态机通过状态图(State Diagram)来表示。

状态图的基本元素

  • 状态(State):对象在其生命周期中的一个条件或情况。
  • 转换(Transition):从一个状态到另一个状态的变化,通常由事件触发。
  • 事件(Event):导致状态转换发生的事情。
  • 动作(Action):在状态转换过程中执行的操作。

复合状态(Composite State)

定义与作用

复合状态是包含一个或多个子状态的状态。它允许我们将复杂的逻辑分解为更小、更易于管理的部分。当对象处于复合状态时,它实际上处于其内部的某个子状态。

实际应用示例

考虑一个“播放界面(PlayerActivity)”的例子,其中包含多种状态:播放中、暂停、缓冲中、错误等。如果将这些状态都放在一个平面状态机里,图表会显得杂乱无章。通过使用复合状态,我们可以将“播放中”这一状态内部的复杂逻辑(如缓冲、暂停等)封装起来,使主状态图保持简洁。
在这个例子中,Playing是一个复合状态,包含了 BufferingPlayingMain和 Paused这些子状态。

子状态机(Submachine State)

定义与优势

子状态机是指一个状态引用了另一个完整的状态机作为其行为定义。与复合状态不同,子状态机允许我们将逻辑拆分到独立的状态机文件中,从而实现更高的复用性。

实际应用示例

以订单状态机为例,PaymentProcess可以作为一个子状态机,引用一个独立定义的“支付子状态机”。这样,支付流程可以在不同的主状态机中被复用。
主状态图:
支付子状态机:
在这个例子中,PaymentProcess是一个子状态机状态,它链接到一个独立定义的支付子状态机。

并行状态(Orthogonal State / Concurrent Region)

为什么需要并行状态?

在许多系统中,一个对象可能同时具有多个独立的状态维度。例如,在一个音乐播放器中,播放状态和网络状态是两个独立的维度,它们可以同时存在并且互不影响。

基本定义与图示

并行状态是一种复合状态,其内部被划分为多个并发区域(Concurrent Region),每个区域拥有自己的子状态机。当对象进入并行状态时,它会同时进入每个并发区域的初始状态,并且各区域独立运行、独立响应事件。
示例:音乐播放器的并行状态
在这个例子中,Active是一个复合状态,内部包含两个并发区域:PlayingRegion(管理播放逻辑)和 NetworkRegion(管理网络连接逻辑)。当进入 Active状态时,系统会同时进入 Stopped(播放区)和 Connected(网络区)这两个区域的初始状态。

实际开发场景

并行状态在以下场景中尤为有用:
  • Android 多模块组件:Activity 同时管理“UI状态”和“网络状态”,这两者相互独立。
  • 后台任务调度:同时有“任务执行状态”和“资源状态”,两者并行变化。
  • 设备控制系统:同时有“电源状态”和“连接状态”,可以同时建模多个子系统。
  • 业务流程并行审批:不同角色并行审批同一请求,各审批流独立运行。

设计要点与常见陷阱

设计要点:
  1. 事件作用域清晰:每个并发区域只响应自己定义的事件,全局事件可由外层复合状态接收并分发。
  1. 状态间通信:可通过共享变量、消息队列、事件总线等方式实现区域间通信;在UML层面上可以使用信号事件(Signal Event)表示通信。
  1. 结束条件:整个并行状态结束通常要求所有区域都进入终止状态,或者定义特定“终止触发事件”来强制退出。
常见陷阱:
  • 区域太多导致复杂:并行区域超过3个时难以维护,建议分层拆分,合理组合。
  • 状态耦合过紧:各区域间应保持逻辑独立,避免过多的相互依赖。
  • 忽略同步点:某些状态需要等待所有区域结束时,可以使用同步伪状态(Join Pseudostate)来协调。
同步伪状态示例:
在这个例子中,“Done → Playing” 模拟了两个区域完成后的“同步点”,即播放和网络都准备好后才能进入“播放中”状态。

UML状态机的实际应用建议

状态分层

  • 不宜过深:一般建议状态分层保持在2~3层,避免过于复杂。
  • 模块化设计:将相关状态分组,使用复合状态或子状态机进行封装,提高可维护性。

复用性与模块化

  • 子状态机的复用:将常用的业务流程(如支付、登录)抽离成独立的子状态机,可以在多个主状态机中复用。
  • 复合状态的封装:将复杂的内部逻辑封装在复合状态中,保持主状态图的简洁性。

清晰的接口

  • 对外暴露的状态转换接口:保持清晰,如“支付成功”、“支付失败”等,便于其他模块理解和调用。
  • 进入与退出动作:将复合状态的进入、退出动作与主逻辑方法对应,确保状态转换时执行必要的操作。

避免常见陷阱

  • 过度细化:不要将状态机过度细化,导致难以维护和理解。
  • 忽视退出动作:确保在退出复合状态时执行必要的清理操作,如释放资源。
  • 同步更新:修改子状态机后,确保所有引用该子状态机的地方都得到同步更新。

总结

UML状态机是描述和控制对象状态及其转换的强大工具。通过掌握复合状态、子状态机和并行状态等高级特性,开发者可以更好地建模复杂的系统行为,提高代码的可维护性和可扩展性。
  • 复合状态(Composite State):适用于封装单个组件内部的复杂状态逻辑,如播放界面中的各种播放状态。
  • 子状态机(Submachine State):适用于抽离和复用模块化的业务逻辑,如支付流程、登录流程等。
  • 并行状态(Orthogonal State / Concurrent Region):适用于描述对象同时处于多个独立状态维度的场景,如同时管理UI状态和网络状态。
 
UML学习——Mermaid常用语法速查UML学习——状态图
Loading...