活动图组成部分名称
活动图里有一种节点叫 决策节点(菱形 ◇)。
它有一个入口和多个出口(带箭头的控制流)。
- 带
【】(通常写作[ ])的表达式 → 监护(Guard Condition)
它是附加在控制流(带箭头的边)上的布尔条件,用于限制这条边能否被激活。
只有当监护为true时,才能沿着这条边从上一个节点转换到下一个节点。 - 不带
【】的具体操作 → 动作(Action)或 活动节点
例如“计算总价”、“发送邮件”、“更新数据库”。
它表示一个可执行的处理步骤,代表从一个状态/节点到另一个节点之间的行为,而不是条件判断。表示一个状态到另外一个状态的转换。
监护
每个出口边上可以写一个条件,用来决定“哪个出口被走”。
这个写在边上的条件,就叫 监护(Guard)。
因为它的唯一作用是:判断“是否允许走这条边”。
- 当
not complete为true时 → 走这条边 - 当
not complete为false时 → 不走这条边
它不负责其他出口的判断,每个出口有自己的监护。
所以 [not complete] 完全符合“监护表达式”的定义:
一个布尔表达式,附加在活动图的控制流上,用来决定该控制流是否被激活。
分支
在活动图里,分支条件不是一个独立元素,而是一组监护的抽象说法。 这里的“分支逻辑”是:
- 如果
complete == true→ 走上面 - 如果
complete == false→ 走下面
你不能说“分支条件就是 not complete”,因为分支是双向的。
但每一条边上那个具体的条件,就是监护。
监护表达式
一个典型的监护表达式长这样(用伪代码):
match value {
Pattern if Guard -> 执行这里
// ↑ 这个 if 后面的就是监护表达式
}
先匹配“形状”,再检查“监护”:
- 先看
value是否符合Pattern(比如是不是一个整数,是不是一个元组等) - 如果符合,再计算监护表达式(普通布尔条件)
- 只有两者都满足,才执行这个分支。
举例对比
只用分支条件(普通 if-else):
def describe(x):
if x > 0 and x < 10:
print("个位数正数")
elif x >= 10:
print("大于等于10")
else:
print("非正数")
用监护表达式(以 Rust 为例,但你可以看逻辑):
match x {
n if n > 0 && n < 10 => println!("个位数正数"),
n if n >= 10 => println!("大于等于10"),
_ => println!("非正数"),
}
看起来好像没区别?但关键差异在于:
- 普通
if里,所有条件都要你自己完整写出来。 - 监护表达式里,你可以先匹配一个类型或结构,再附加条件。例如:
match maybe_number {
Some(n) if n > 0 => println!("正数"),
Some(n) => println!("非正数或零"),
None => println!("没有数字"),
}
这里 Some(n) 是“形状”(这是一个 Option 且包含值),if n > 0 是监护表达式。
如果用普通分支条件,你需要先判断是否 Some,再取出值,再判断 >0,代码更长。
一句话总结区别
| 分支条件 | 监护表达式 | |
|---|---|---|
| 出现在 | if、else if、switch 等 | 模式匹配(match、case 等)内部 |
| 作用 | 单独决定分支 | 先匹配结构,再附加条件 |
| 能不能单独使用 | 能 | 不能,必须依附于某个模式 |
通俗说法:
- 分支条件 = “问一个问题”(比如:分数 >= 60 吗?)
- 监护表达式 = “先看这东西长啥样,再问一个问题”(比如:这是一个装整数的盒子吗?如果是,里面的数大于 0 吗?)