
3.2 用例关系和描述
用例除了与其参与者发生关联外,还可以具有系统中的多个关系,这些关系包括包含关系、扩展关系和泛化关系,而应用这些关系的目的是从系统中抽取出公共行为和其变体。
3.2.1 泛化关系
泛化是一种表示UML中项目的继承关系的技术。泛化可以应用于参与者和用例中来表示其子项从父项继承的功能,而且泛化还表示了父项的每个子项都有略微不同的功能或目的,以确保自己的唯一性。泛化可以用于用例,也可以用于参与者。
1.泛化用例
相对于参与者而言,用例泛化更易理解。用例泛化是指一个用例(一般为子用例)和另一个用例(父用例)之间的关系,其中父用例描述了子用例与其他用例共享的特性,而这些用例是有着同一父用例的。
泛化将特化用例和一般用例联系起来。即子用例是父用例的特化,子用例除具有父用例的特性外,还可以有自己的另外特性。父用例可以被特化成一个或多个子用例,然后用这些子用例来代表父用例的更多明确的形式。
泛化的标记非常简单,它使用一条实线和三角箭头连接父用例和子用例,由子用例指向父用例,如下图所示。

因为父用例“身份验证”是抽象的,它并不提供具体的身份验证方法,所以一个具体的子用例必须提供具体的功能。
子用例“口令验证”提供的身份验证方法为:
□ 从主数据库获得密码。
□ 请求使用密码。
□ 用户提供密码。
□ 在用户登录时检查密码。
子用例“指纹验证”提供的身份验证方法为:
□ 得到来自主数据库的指纹特征。
□ 扫描用户的指纹特征。
□ 将主数据库指纹特征和扫描特征比较。
深入研究本示例,会发现身份验证不只有两个子用例。下图演示了一个父用例的多个子用例。

泛化甚至可以分层,父用例的子用例也可以有自己的子用例,如下图所示。

2.泛化参与者
与用例一样,也可以对参与者进行泛化。泛化后的参与者也在系统中扮演较为具体的角色。如下图所示,假设图书管理系统中,管理员分为对系统进行维护的管理员和完成借书、还书等日常操作的图书管理员。参与者“经理”描述了参与者“图书管理员”和“管理员”所扮演的一般角色。如果不考虑与系统交互时的职责,可以使用一般角色的参与者“经理”。如果强调管理员的职责,那么用例须使用精确的参与者,即子类“图书管理员”和“管理员”。

除此之外,还可以将泛化后的用例与泛化后的参与者相联系起来,如下图所示的泛化的用例与泛化的参与者相关联。

3.2.2 包含关系
在对系统进行分析时,通常会发现有些功能在不同的环境下都可以被使用。在编写代码时,希望编写可重用的构件,这些构件包括诸如可以从其他代码中调用或参考的类库、子过程以及函数。虽然每个用例的实例都是独立的,但是一个用例可以用其他的更简单的用例来描述。用例图中UML包含关系就支持这种做法。
包含关系指:一个用例可以简单地包含其他用例具有的行为,并把它所包含的用例行为作为自身行为的一部分。这种情况下,新用例不是初始用例的一个特殊例子,并且不能被初始用例所代替。包含关系把几个用例的公共步骤分离成一个单独的被包含用例。
如果两个以上用例有大量一致的功能,则可以将这个功能分解到另一个用例中。其他用例可以和这个用例建立包含关系。
一个用例的功能太多时,可以用包含关系建模两个小用例。
被包含用例称作提供者用例,包含用例称作客户用例,提供者用例提供功能给客户使用。
在UML中,包含关系表示为虚线箭头加<<include>>字样,箭头指向被包含的用例。如下图所示是图书管理系统中的包含关系。

为了更好地理解包含关系是如何起作用的,下面列出了“商品信息系统”和“建材信息系统”使用已经存在的被包含用例,如下图所示。

为了使用包含关系,用例必须遵循以下两个约束条件。
□ 客户用例只依赖于提供者用例的返回结果,不必了解提供者用例的内部结构。
□ 客户用例总会要求提供者用例执行,对提供者用例的调用是无条件的。
在为系统建模时,使用包含关系是十分明智的。因为它有助于在将来实现系统时,确定哪里可以重用某些功能,在编写代码时就可实现代码的重用,从而从长远意义上缩短系统的开发周期。
3.2.3 扩展关系
扩展关系是一种依赖关系,它指一个用例可以增强另一个用例的功能,是把新的行为插入到已有用例中的方法。
基础用例的扩展增加了原有的功能,此时是基础用例被作为用例使用,而不是扩展用例。
基础用例提供了一组扩展点,在这些新的扩展点中可以添加新的行为,而扩展用例提供了一组插入片段,这些片段能够被插入到基础用例的扩展点上。
基础用例不必知道扩展用例的任何细节,它仅为其提供扩展点。
基础用例即使没有扩展用例也是完整的,这点与包含关系有所不同。
一个用例可能有多个扩展点,每个扩展点也可以出现多次。一般情况下,基础用例的执行不会涉及扩展用例,只有特定的条件发生,扩展用例才被执行。
扩展关系为处理异常或构建灵活的系统框架提供了一种十分有效的方法。
在UML中,扩展关系表示为虚线箭头加<<extend>>字样,箭头指向被扩展的用例(即基础用例),箭头的尾部则处在扩展用例上,如下图所示是扩展关系标识符。

下面的示例将演示在图书管理系统中如何使用扩展关系:超期处理用例由通知超期用例进行扩展,如下图所示。

在本示例中,基础用例是超期处理,扩展用例是通知超期。如果借阅者按时归还图书,那么就不会执行通知超期用例。而当归还图书时超过了规定的时间,则超期处理用例就会调用通知超期用例提醒管理员对此进行处理。
正如上图中所表示的,通知超期用例指向超期处理用例。这样绘制的原因是因为通知超期用例扩展了超期处理用例,即通知超期用例是添加到超期处理用例中的一项功能,而不是超期处理用例每次都调用通知超期用例。如果每次检查是否超期时都要提醒图书管理员,那么就要使用如下图所示的包含关系。

在理解了什么是扩展用例,以及使用它的原因后,那么如何知道图书管理员何时被提醒呢?毕竟这只在所借阅的图书超期时才被提醒,而且不是随时提醒的。本示例设定为当某学生所借阅的图书中有超期借阅时,图书管理员才会被提醒。为此,UML提供了扩展点来解决该问题。扩展点的定义为:基础用例中的一个或多个位置,在该位置会衡量某个条件以决定是否启用扩展用例。下图为一个扩展点的标记符。

如上图所示,一个水平线分隔了基础用例,而基础用例的用例名移到了椭圆的上半部分。椭圆的下半部分则列出了启用扩展用例的条件。
下图使用包含扩展点标记符的基础用例来表明如果借阅者有超期的借阅信息,那么基础用例则启用扩展用例通知图书管理员。

如上图所示,扩展点中有一个判断条件,以决定扩展用例是否会被使用,在包含关系中没有这样的条件。扩展点定义了启用扩展用例的条件,一旦该条件满足,则扩展用例将被使用。例如,当某学生的借阅信息中有超期的借阅信息时,则基础用例ProcessOverTime会使用NotifyOverTime用例,以通知图书管理员该学生有图书超期未还。当执行完扩展用例NotifyOverTime后,基础用例将继续执行。
扩展点的表示符号可以按照下面的格式添加到椭圆中,即:
<extension point>::=<name> [:<explanation>]
其中,name指扩展点的名称,因为一个基础用例可以有多个扩展用例。扩展点的名称描述了用例中的某个逻辑位置。因为用例描述的是功能和行为,所以该位置通常是对象在执行过程中某时间的状态。explanation为对扩展点的解释,它为一个可选项。该项可以是任何形式的文本,只要把问题交代清楚即可。需要注意,在绘制扩展点时,并不是所有的UML建模工具都支持上述命名方法。
除在基础用例上使用扩展点控制什么时候进行扩展外,扩展用例自身也可以包含条件。扩展用例上的条件是作为约束使用的,在扩展点成立的时候,如果该约束表达式也得到了满足,则扩展用例才执行,否则不会执行。
3.2.4 用例描述
用例图描述了参与者和系统特征之间的关系,但是它缺乏描述系统行为的细节。所以一般情况下,还会以书面文档的形式对用例进行描述,每个用例应具有一个用例描述。在UML中对用例的描述并没有硬性规定,但一般情况下用例描述应包括以下几个方面内容。
1.名称
名称无疑应该表明用户的意图或用例的用途,如上面示例中的“借阅图书”“归还图书”。
2.标识符[可选]
唯一标识一个用例,如“UC200601”。这样就可在项目的其他元素(如类模型)中用它来引用这个用例。
3.参与者[可选]
与此用例相关的参与者列表。尽管这则信息包含在用例本身当中,但在没有用例图时,它有助于增加对该用例的理解。
4.状态[可选]
指示用例的状态,通常为以下几种之一:进行中、等待审查、通过审查或未通过审查。
5.频率
参与者使用此用例的频率。
6.前置条件
一个条件列表。前置条件描述了执行用例之前系统必须满足的条件。这些条件必须在使用用例之前得到满足。前置条件在使用之前,已经由用例进行过测试。如果条件不满足,则用例不会被执行。
前置条件非常类似于编程中的调用函数或过程,函数或过程在开始部分对传递的参数进行检测。如果传递的参数无法通过合法检查,那么调用的请求将会被拒绝。同样这也适用于用例。例如,当学生借阅图书时,借出图书用例需要获取学生借书证信息,但如果学生使用了一个已经被注销的借书证,那么用例就不应该更新借阅关系;另外,如果学生归还了从系统中已经删除的一本图书,那么用例就不能让还书操作完成。
借阅图书用例的前置条件可以写成下面的形式。
前置条件:学生出示的借书证必须是合法的借书证。
7.后置条件
后置条件将在用例成功完成以后得到满足,它提供了系统的部分描述。即在前置条件满足后,用例做了什么?以及用例结束时,系统处于什么状态?因为并不知道用例终止后处于什么状态,因此必须确保在用例结束时,系统处于一个稳定的状态。例如,当借阅图书成功后,用例应该提供该学生的所有借阅信息。
借阅图书用例的后置条件可以写成下面的形式。
后置条件:借书成功,则返回该学生借阅信息;借书失败,则返回失败的原因。
8.假设[可选]
为了让一个用例正常运行,系统必须满足一定的条件,在没有满足这些条件之前,系统不会调用该用例。假设描述的是系统在使用用例之前必须满足的状态,这些条件并没有经过用例的检验,用例只是假设它们为真。例如,身份验证机制,后继的每个用例都假设用户是在通过身份验证以后访问用例的。应该在一定的时候检验这些假设,或者将它们添加到操作的基本流程或可选流程中。
下面是借阅图书用例的假设条件。
假设:图书管理员已经成功登录到系统。
9.基本操作流程
参与者在用例中所遵循的主逻辑路径。因为它描述了当各项工作都正常进行时用例的工作方式,所以通常称其为适当路径或主路径。操作流程描述了用户和执行用例之间交互的每一步。描述操作流程是一项将个别用例进行合适细化的任务。通过这种做法,常常可以发现自己原始的用例图遗漏了哪些内容。
借出图书用例的基本操作流程如下。
(1)管理员输入借书证信息。
(2)系统要确保借书证信息的有效性。
(3)检查是否有超期的借阅信息。
(4)管理员输入要借阅的图书信息。
(5)系统将学生的借阅信息添加到数据库中。
(6)系统显示该学生的所有借阅信息。
10.可选操作流程
可选操作流程包括用例中很少使用的逻辑路径,那些在变更工作方式、出现异常或发生错误的情况下所遵循的路径。例如,借出图书用例的可选操作流程包括:输入的借书证信息不存在,该借书证已经被注销或有超期的借阅信息等异常情况下,系统采取的应急措施。
11.修改历史记录[可选]
修改历史记录是关于用例的修改时间、修改原因和修改人的详细信息。下表是一个对用例“归还图书”的描述。

上表所示的格式和内容只是一个示例,开发人员可以根据自己的情况定义。但要记住,用例描述及它们所包含的信息,不仅是附属于用例图的额外信息。事实上,用例描述让用例变得完整,没有用例描述的用例没什么意义。
随着更多的用例细节被写到用例描述中,往往还会发现用例图中遗漏的某些功能。在模型的各个方面也会出现同样的问题:加入的细节越多,越可能必须回头更正以前所做的事。这是一个反复系统开发工作的内涵。进一步精炼系统模型是件好事,开发工作的每一次反复,都可以使系统模型更好、更准确。