开始之前,先简单说说什么是静态和动态建模. 对象模型有两种类型: 动态和静态. 动态模型有助于设计逻辑、代码行为或方法体,例如UML交互图(顺序图或通信图). 静态模型有助于设计包、类名、属性和方法特征标记(但不是方法体)的定义,例如UML类图.

静态和动态建模之间具有关系,敏捷建模对此的实践是并行创建模型: 花费较短的时间创建交互图(动态), 然后转到对应的类图(静态), 交替进行. UML初学者一般会认为静态视图的类图是重要的图形,但事实上,大部分具有挑战性、有益和有效的设计工作都会在绘制UML动态视图的交互图的时候发生. 分析需要哪些对象、发送哪些消息、发送给谁、以何种顺序发送等具体问题,确定它们是如何通过消息和方法进行协作,通过动态对象建模(例如绘制顺序图)才能真正落实这些准确和详细的结论. 因此应该花费时间使用交互图进行动态对象建模,而不仅是使用类图进行静态对象建模.

UML使用交互图来描述对象间通过消息的交互. 交互图可以用于动态建模. 交互图有两种类型: 顺序图和通信图. 这里主要介绍一下顺序图.

顺序图以一种栅栏格式描述交互,其中在右侧添加新创建的对象, 它能够清晰表示消息的顺序和时间排序, 如下图所示:

UML顺序图示例 ___

以上图形映射成代码可能的情形是,类A具有名为doOne的方法和类型为B的属性,同时类B具有名为doTwo和doThree的方法. 由此,类A的定义片段可能如下:

1
2
3
4
5
6
7
8
9
10
11
public class A
{
private B myB = new B();

public void doOne() {
myB.doTwo();
myB.doThree();
}

//...
}

常用的UML交互图表示法

这一节所说的表示法适用于顺序图和通信图,包括如下几种. ####使用生命线框图表示参与者 在UML中,生命线框图使用方框图表示,通俗地讲,它们是交互的参与者,并且将生命线框图等同于类的实例. 下图所示是UML中生命线框图的常用表示法.

交互中参与者的生命线框图 ___

消息表达式的基本语法

交互图展示了对象之间的消息,UML对于这些消息表达式具有标准语法:

return = message(parameter : parameterType) : returnType

没有参数时可以省略圆括号,这是合法的. 如果明显或者不重要,消息表达式中可以不包含类型信息,例如:

1
2
3
4
5
initialize(code)
initialize
d = getProductDescription(id)
d = getProductDescription(id : ItemID)
d = getProductDescription(id : ItemId) : ProductDescription

单实例类对象

在OO设计模式中,有一种特别常见的模式称为单实例类模式(Singleton). 该模式所暗含的意思是,对类进行实例化时,只能存在一个实例,而决不能是两个. 在UML交互图(顺序图或者通讯图)中,遇到此类对象时,需再生命线框图右上角标识 “1”. 单实例类的例子如下图所示.

交互图中的单实例类 ___

顺序图的基本表示法

生命线框图和生命线

与通信图相比,顺序图中的生命线框图包括框图之下的垂直延伸线,这是实例的生命线. 尽管实际中所有UML示例都用虚线表示生命线(源于UML1的影响), 但事实上UML2规范中定义的生命线可以是实线也可以是虚线. ####消息 在垂直生命线之间,用带实心箭头的实线并附以消息表达式的方式表示对象间的每个消息(同步消息), 如下图所示,其中生命线自上而下表示时间顺序.

消息和控制期的执行规格条 ___

上图中,最开始的消息在UML中成为创始消息(found message), 以实心圆作为起点来表示此类消息. 创始消息表示没有特定发送者、发送者不明确或消息源众多的消息. 然而,小组或者工具可以忽略这一点,而是使用常规的消息连线表示,约定其表示的是创始消息.

控制期和执行规格条

如图消息和控制期的执行规格条中,顺序图中可以使用执行规格条(UML1中称为活动条或者简称为活动)来表示控制期(focus of control, 在常规阻塞调用中,将操作置于调用堆栈中),通常在使用UML CASE工具时会经常绘制执行规格条,但是在墙上绘制草图时往往不会绘制执行规格条, 绘制执行控制条是可选的. ####表示应答或返回 可以用以下两种方式表示消息的返回结果:

  • 使用消息语法 returnVar = message(parameter)
  • 在活动条末端使用应答(或返回)消息线

上述两种方法都很常见,建议在草图中使用第一种方法,因为这种方法比较简单. 如果使用应答线,一般要在线上加以标记描述返回值, 如下图所示.

表示消息返回结果的两种方式 ___

发送给“自身”的消息

可以使用嵌套的活动条表示对象发送给自身的消息,如下图所示:

发送给自身的消息 ___

实例的创建

下图展示的是创建对象的表示法. 需要注意的是UML使用的是虚线(许多作者采用了使用实线的示例,而且规范的早期草案中也是如此). 实心箭头表示常规的同步消息,开放箭头表示异步调用. 消息名称中的create不是必需的,这只是UML的习惯用法.带有实心箭头的虚线上的create消息通常可以解释为“调用操作符new并调用其构造器”.

实例的创建和对象的生命线 ___

对象生命线和对象的销毁

在某些情况下,需要显示地表示对象的销毁,例如,当使用没有自动垃圾回收机制的C++时,或者当需要特别指明对象不再使用时(例如关闭数据库连接),都需要如此表示. UML生命线表示法提供了表示销毁的方式,如上图 实例的创建和对象的生命线 所示.

UML顺序图中的图框

为了支持有条件和循环的构造,UML使用了图框,图框是图的区域或者片段,在图框中具有操作符或标签(例如loop)和保护信息(条件子句), 如下图所示.

UML图框的示例 ___

下列是一些常用的图框操作符:

  • alt: 选择性的片段,用于表示保护信息所表达的互斥条件逻辑
  • loop: 用于表示保护信息为真的循环片段,也可以写为loop(n)以指明循环的次数,用loop(i, 1, 10)表示for循环
  • opt: 当保护信息为真时执行的可选片段
  • par: 并行执行的并行片段
  • region: 只能执行一个线程的临界片段

有条件消息

opt图框位于一个或多个消息周围. 注意,其中的保护信息要置于相关的生命线之上. 如下图所示.

有条件消息 ___

在UML 2.x表示法中,对单一的有条件消息的表示需要在一个消息周围放置完整OPT图框,如上图所示. 在UML 1.x的顺序图中,对这种情况可使用如下图所示的表示法, 在绘制UML草图时,可对这种简单的单一消息使用UML 1风格.

UML 1.x表示法中的有条件消息 ___

互斥的有条件消息

使用ALT图框放置于互斥的可选条件周围,如下图所示.

互斥的有条件消息 ___

对集合的迭代

对集合(例如list或map)中所有成员进行迭代的常用算法是向每个成员发送同一条消息。在这种情况下,通常会使用某种迭代器(iterator)对象,例如java.util.Iterator或C++标准库迭代器的实现. 下图中给出了对集合迭代的一种表现方式.

使用相对直接的表示法对集合进行迭代 ___

需要注意上图中生命线上的选择器表达式lineItem[i]. 选择器表达式用于在一组对象中选择一个对象. 生命线参与者应该表示一个对象,而不是集合. 下图表示了对集合进行迭代的另一种表现方式.

隐含地表达对集合的迭代 ___

图框的嵌套

UML中图框是可以嵌套的,如下图所示.

图框的嵌套 ___

如何关联交互图

交互具体值(interaction occurrence, 也称为交互使用, interaction user)是在交互中引用另一交互. 当想要简化图时,将其中的一部分分解到另一个图中,或者存在可复用的交互具体值时,这种做法十分有效. UML工具利用了这一做法,以助于关联和链接图形.

可以使用两种图框来创建交互图的关联:

  • 在整个顺序图的周围放置图框,并加上sd标记和诸如AuthenticateUser这样的名称.
  • 标记为ref的图框称为引用,该引用指另一个已命名顺序图. 所指的顺序图是实际的交互具体值.

交互总览图包含了一系列引用框图(交互具体值). 总览图将这些引用组织为更大规模的逻辑和过程流的结构. 任何顺序图都可以使用sd图框围绕起来,并对其命名. 当需要引用响应名字的sd图框时,可以使用ref图框. 关联交互图的示例如下:

交互具体值的示例 ___

对类调用静态(或类)方法的消息

可以通过使用生命线框图标记来表示对类或静态方法的调用,其中的生命线框图表示接受消息的对象是类,或者更准确地说是元类(meta-class)的示例,如下图所示:

调用类或静态方法, 以元类的实例表示类对象 ___

多态消息和案例

多态性是OO设计的基础, 在UML的顺序图中表示多态性,一种方法是使用多个顺序图,其中一个表示到抽象超类或接口对象的多态消息,其余的顺序图分别详细表示每一种多态案例,其中每个顺序图都以创始的多态消息作为起点,如下图描述所示:

用顺序图对多态案例建模的方法 ___

异步和同步调用

异步消息调用不等待响应,不会阻塞. 异步消息可以在多线程坏境中使用,因此能够创建和初始化新的执行线程. UML中利用刺形箭头消息表示异步调用,常规同步(阻塞)调用用实心箭头表示,如下图所示.

异步调用和主动对象 ___