技术开发 频道

UML 基础: 序列图

  【IT168 技术文章】

         图的目的  

  序列图主要用于按照交互发生的一系列顺序,显示对象之间的这些交互。很象类图,开发者一般认为序列图只对他们有意义。然而,一个组织的业务人员会发现,序列图显示不同的业务对象如何交互,对于交流当前业务如何进行很有用。除记录组织的当前事件外,一个业务级的序列图能被当作一个需求文件使用,为实现一个未来系统传递需求。在项目的需求阶段,分析师能通过提供一个更加正式层次的表达,把用例带入下一层次。那种情况下,用例常常被细化为一个或者更多的序列图。

  组织的技术人员能发现,序列图在记录一个未来系统的行为应该如何表现中,非常有用。在设计阶段,架构师和开发者能使用图,挖掘出系统对象间的交互,这样充实整个系统设计。

  序列图的主要用途之一,是把用例表达的需求,转化为进一步、更加正式层次的精细表达。用例常常被细化为一个或者更多的序列图。序列图除了在设计新系统方面的用途外,它们还能用来记录一个存在系统(称它为“遗产”)的对象现在如何交互。当把这个系统移交给另一个人或组织时,这个文档很有用。

  符号

  既然这是我基于 UML 2的 UML 图系列文章的第一篇,我们需要首先讨论对 UML 2 图符号的一个补充,即一个叫做框架的符号元件。在 UML 2中,框架元件用于作为许多其他的图元件的一个基础,但是大多数人第一次接触框架元件的情况,是作为图的图形化边界。当为图提供图形化边界时,一个框架元件为图的标签提供一致的位置。在 UML 图中框架元件是可选择的;就如你能在图 1 和 2 中见到的,图的标签被放在左上角,在我将调用框架的“namebox”中,一种卷角长方形,而且实际的 UML 图在较大的封闭长方形内部定义。

  图 1: 空的 UML 2 框架元件

  除了提供一个图形化边框之外,用于图中的框架元件也有描述交互的重要的功能, 例如序列图。在序列图上一个序列接收和发送消息(又称交互),能通过连接消息和框架元件边界,建立模型(如图 2 所见到)。这将会在后面“超越基础”的段落中被更详细地介绍。

  图 2: 一个接收和发送消息的序列图

  注意在图 2 中,对于序列图,图的标签由文字“sd”开始。当使用一个框架元件封闭一个图时,图的标签需要按照以下的格式:

1  图类型 图名称

 

  UML 规范给图类型提供特定的文本值。(举例来说,sd代表序列图,activity代表活动图,use case代表用例图)。

  基础

  序列图的主要目的是定义事件序列,产生一些希望的输出。重点不是消息本身,而是消息产生的顺序;不过,大多数序列图会表示一个系统的对象之间传递的什么消息,以及它们发生的顺序。图按照水平和垂直的维度传递信息:垂直维度从上而下表示消息/调用发生的时间序列,而且水平维度从左到右表示消息发送到的对象实例。

  生命线

  当画一个序列图的时候,放置生命线符号元件,横跨图的顶部。生命线表示序列中,建模的角色或对象实例。 1 生命线画作一个方格,一条虚线从上而下,通过底部边界的中心(图 3)。生命线名字放置在方格里。

  图 3: 用于一个实体名为freshman的生命线的Student类的一个例子

  UML 的生命线命名标准按照如下格式:

1 实体名 : 类名
2

  在如图3所示的例子中,生命线表示类Student的实体,它的实体名称是freshman。这里注意一点,生命线名称带下划线。当使用下划线时,意味着序列图中的生命线代表一个类的特定实体,不是特定种类的实体(例如,角色)。在将来的一篇文章中,我们将会了解结构化建模。现在,仅仅评述序列图,可能包含角色(例如买方和卖方),而不需要叙述谁扮演那些角色(例如Bill和Fred)。这准许不同语境的图重复使用。简单拖放,序列图的实例名称有下划线,而角色名称没有。

  图 3 中我们生命线例子是一个命名的对象,但是不是所有的生命线都代表命名的对象。相反的,一个生命线能用来表现一个匿名的或未命名的实体。当在一个序列图上,为一个未命名的实例建模时,生命线的名字采用和一个命名实例相同的模式;但是生命线名字的位置留下空白,而不是提供一个例图名字。再次参考图 3,如果生命线正在表现Student类的一个匿名例图,生命线会是: “Student”。同时, 因为序列图在项目设计阶段中使用,有一个未指定的对象是完全合法: 举例来说,“freshman”。

  消息

  为了可读性,序列图的第一个消息总是从顶端开始,并且一般位于图的左边。然后继发的消息加入图中,稍微比前面的消息低些。

  为了显示一个对象(例如,生命线)传递一个消息给另外一个对象,你画一条线指向接收对象,包括一个实心箭头(如果是一个同步调用操作)或一个棍形箭头(如果是一个异步讯号)。消息/方法名字放置在带箭头的线上面。正在被传递给接收对象的消息,表示接收对象的类实现的一个操作/方法。在图 4 的例子中,analyst对象调用ReportingSystem 类的一个实例的系统对象。analyst对象在调用系统对象的 getAvailableReports 方法。系统对象然后调用secSystem 对象上的、包括参数userId的getSecurityClearance 方法,secSystem的类的类型是 SecuritySystem。 2

  图 4: 一个在对象之间传递消息的实例

  除了仅仅显示序列图上的消息调用外,图 4 中的图还包括返回消息。这些返回消息是可选择的;一个返回消息画作一个带开放箭头的虚线,向后指向来源的生命线,在这条虚线上面,你放置操作的返回值。在图 4 中,当 getSecurityClearance 方法被调用时,secSystem 对象返回 userClearance 给系统对象。当 getAvailableReports 方法被调用时,系统对象返回 availableReports。

  此外,返回消息是序列图的一个可选择部分。返回消息的使用依赖建模的具体/抽象程度。如果需要较好的具体化,返回消息是有用的;否则,主动消息就足够了。我个人喜欢,无论什么时候返回一个值,都包括一个返回消息,因为我发现额外的细节使一个序列图变得更容易阅读。

  当序列图建模时,有时候,一个对象将会需要传递一个消息给它本身。一个对象何时称它本身?一个纯化论者会争辩一个对象应该永不传递一个消息给它本身。然而,为传递一个消息给它本身的对象建模,在一些情境中可能是有用的。举例来说,图 5 是图 4 的一个改良版本。 图 5 版本显示调用它的 determineAvailableReports 方法的系统对象。通过表示系统传递消息“determineAvailableReports”给它本身,模型把注意力集中到过程的事实上,而不是系统对象。

  为了要画一个调用本身的对象,如你平时所作的,画一条消息,但是不是连接它到另外的一个对象,而是你把消息连接回对象本身。

  图 5: 系统对象调用它的 determineAvailableReports 方法

  图 5 中的消息实例显示同步消息;然而,在序列图中,你也能为异步消息建模。一个异步消息和一个同步的画法类似,但是消息画的线带一个棍形矛头,如图 6 所示。

  图 6: 表示传递到实体2的异步消息的序列图片段

     

1
相关文章