参考《UML面向对象系统分析与设计教程》

第五章    对象图和类图

5.1 概述

    UML的类图和对象图表达的是对象模型的静态结构方面。它不仅定义系统中的类,表示类之间的联系,如关联、依赖、聚合等,还包括类的内部结构,如类的属性和操作等。

    类图描述的是一种静态关系,在系统的整个生命周期都是有效的。通过分析问题域和用例,就可以得到相关的类,然后再把逻辑上相关的类封装成包。这样可以很好地体现出系统的分层 结构,使人们对系统层次关系一目了然。

    一个对象图是类图的一个实例,对象图只能在系统的某一时间存在。

5.2 对象类定义

    类是对一组具有相同属性、操作、关系和语义的对象的描述。

    类的名称:

    如“学校::教师”,其中“学校”是类“教师”所在的包名。

    定义属性:

    wKiom1amz-fg0kV8AAATpugooOU761.png

    类中属性的可见性主要包括public private 和protected,分别是+ - #。(package用~符号)

    类的属性必须有一个名字以区别于类的其他属性。冒号:后紧跟属性值的数据类型,数据类型的表示依赖于实现语言。类型后的“=初始值”表示新建该对象时该属性的初始值。

    在类的属性框中,方括号“【】”中的部分是可选项目。方括号中的多重性用多值表达式表示,其值是该对象类的每个实例的属性值的个数。多值表达式的格式为:

        integer, integer,...... 或低界...高界

    (书中的图是图中上面的图,在Jude中,[多重性]符号显示在类型后面,如图中下面的图)

    其中低界表示多值表达式的最小值,高界为多值表达式的最大值,"低界...高界"表示属性必定在此范围内取值。低界和高界可以是一个×××数或星号“*”,表示任意的非负整数。例如,“0...*”表示0个或无限多个。“职务【2】:string”表示有2个值,数据类型为“string”;“姓名【0...1】:string”说明属性“姓名”可以为空或一个姓名值,数据类型为“string”。

    属主范围是属性的另一个重要性质。属主范围有两种情况:实例和分类。如果一个属性的属主范围是实例,则该对象 类的每一个实例对象都有一个自己的该属性的值要一个属性的属主范围是分类符,则对于该对象类本属性只有一个值,该对象类的每一个实例对象都持有此唯一的值,该对象类该属性名下应加下划线。对象类的大多数属性的属主范围都是实例。(类似于static关键字)

    定义操作

    操作的可视性的含义和表示方法与类的属性相同。

    一个操作可以有参数,也可以没有参数。参数列表由逗号分隔的操作的形式参数组成,格式为:

        参数名:类型=默认值,...

    冒号“:”后紧跟返回列表,返回列表规定了当该操作完成时的返回值的类型,它由逗号分隔的操作的返回值类型表达式组成,基格式为:

        返回类型

        返回名字=类型,...

    操作也有属主范围的区分,它的含义与表示方法与类的属性相同。对象的构造操作(构造函数)必须带有下划线,表示它的属主范围是分类符。构造操作也可以用构造型<<constructor>>表示。

    操作定义的最后花括号{}中的性质,是一个文字串,说明该操作的一些有关信息。性质是一个可选项。

(在Jude中,性质是点击“约束”进行修改)

    wKiom1am1rPheOpAAAAViHNvQR8845.png

5.3 对象类的关联

    5.3.1 关联的定义

    在对象类图上,关联用一条实线表示。一个关联至少有两个关联端,每个关联端连接到一个类,关联端是有序的。关联线旁可以标出关联的名字,线旁的小实心箭头表示关联的方向,从源对象类指向目标对象类。关联可以是单向的或双向的,如果是双向的则不必标出方向箭头。

wKioL1am2-CT1MsvAAAWODUGPtM574.png

    在UML类图中,关联的每个端点都可以带有一个多重性标注。关联的多重性标注用于指定关联的另一站内所链接的类的一个实例可以和多少个对象相连。常用的多重性标记有0...1,1,* 等。

wKiom1am3YGzOFfoAAARMnDHP6o672.png

    在关联的对象类图标旁可以标注类的角色名(Role)。角色表示被关联的类参与关联的特定的行为。角色名可以后跟一个冒号“:”和类名。

    限定符可以有名字或标识,表示被管理的对象的一个属性或多个属性的列表。限定符包含在一个小矩形内,限定符的名字可以默认省略。例如,下图中“订货”带有限定符“ProductID:Int“,它限定订货的产品ID必须为整数。该限定符说明,在与”订货“的链接中,每一个由整型数标识的产品,可以由一条订货作业线来处理。(Jude上不知道怎么加入限定,尝试用画图工具画出书上的图)

wKiom1am6maQJBZlAAASzw-HapM176.png

    关联本身也有特性,通过关联对象类可以进一步说明关联的属性、操作及其他信息。关联对象类(或称为关联类)是一个关联,也是一个类,它定义了一组属于该关联的特性,这些特性不属于被关联的任何一个对象类。关联类的图标用一条虚线连到关联线上。

wKioL1am7gfjqq0TAAATsBG0ADc647.png

    5.3.2 关联类型

    对象类之间的关联有以下几种类型,自反关联,二元关联和N元关联。

    5.3.3 聚合和组合

    聚合和组合是对象类之间的一种特殊的关联关系,它主要用来描述对象类之间的整体与部分之间的关系。

    聚合用于表示事物的整体/部分关系较弱的情况,整体对象拥有部分对象。在UML中,聚合关联用带有空心的菱形头的实线表示。在聚合中,代表部分事物的对象可以属于多个聚合对象,可以为多个聚合对象共享,而且可以随时改变它们所从属的聚合对象。部分对象与整体对象的生存期无关,一旦删除了它的一个聚合对象,不一定就随即删除代表部分事物的对象。

wKiom1anLjPgYtVcAAAZz_EK06g996.png

    组合表示事物的整体 与部分关系较强的情况。在UML类图中,组合关联用带有实心菱形头的实线表示。在组合中,代表整体事物的组合对象负责创建和删除代表部分事物的对象,代表部分事物的对象只属于一个组合对象,而且与组合对象同时存在,同时消失,一旦删除组合对象,也就随即删除了相应的代表部分事物的对象。

    5.3.4 泛化

    泛化是一般事物和该事物较为特殊的种类之间的关系,子类继承父类的属性和操作外,通常子类还添加新的属性和操作,或者修改了父类的某些操作。

    在UML类图中,泛化用从子类指向父类的空心三角形箭头表示。对象类“大学”、“小学“是泛化对象类“学校”的子类。

wKiom1anLh2SUxCpAAASiT2AvB4670.png

    5.3.5 依赖

    依赖是指一个模型元素(提供者)的变化必然影响另一个模型元素(客户)。例如,课表信息依赖于课程信息,如果删除了课程信息,所有关于该课程的排课信息也连带被删除。

    在UML中,把依赖描述成一条有方向的虚线,指向被依赖的对象。依赖可以有自己的名字,但一般都省略。对于依赖可以加上构造型,规定依赖的含义和作用,常用的构造型有<<use>(使用),<<call>>(调用 ),<<instantiate>>(实例)和<<friend>>(友元)等。类“电视”的方法“换台”使用了类“频道”的对象作为参数。因此这两个类之间存在着使用依赖关系。wKiom1anLguCbWsKAAATBACq1BM300.png

5.4 对象图

    在建立系统模型时,一般采用对象类图表示系统的静态特征,用交互图表示系统的动态特征。对象图则冻结了系统的某一瞬间,表达系统的对象在该时刻的具体状态(属性值和操作)。

    对象的图标与对象类一样用实线矩形表示,矩形框中含有若干分隔区,分别表示对象的名称、属性及其他成分等。对象各是一个文字串,必须带有下划线。冒号“:”后跟一个由逗号分隔的类列表,它指出对象所属的型或类。

    对象的属性分隔区含有该对象的属性值,属性值的数据类型必须符合该对象所属的类的规定。

    下图是对某学校建模的一组对象。该图描述了该学校的部门组成情况。a是类“University”的对象,这个对象与对象b1,b2,b3相链接,b1,b2,b3都是类“Department"的对象,它们具有不同的属性值,即有不同的名字。

    在图中没有显示对象所能进行的操作,但是每一个对象都可以进行所属的类的定义的操作。例如,对象p1可以进行”Employee“类的所有操作。

wKioL1aoHACS-unSAAAhsGbvkSw919.png

5.5 接口

    接口是一组外部可以访问的操作,用于为对象类或构件提供服务。接口可以看作是一种特殊的抽象类,它不含属性,它的操作也没有方法,即没有操作的实现。

    接口可以用一个类图标表示。在接口图标的名字分隔区中有唯一的接口名,接口名可以是简单名,也可以是路径名,接口名前有构造型<<interface>>。接口图标中没有属性分隔区,在操作分隔区中列出抽象的公共操作,参数可有可无。

    接口也可以用一个小圆表示,圆旁标有接口的名字,称为棒糖式接口。如图,这种简单形式对于在建立模型时只打算了解系统内部的接缝的情况是有效的。

wKioL1aoH1KjgmwaAAAZf-UIpn0771.png

    接口可以通过一个实现联系获得其他对象类的支持,这些对象类提供在接口中定义的全部操作。实现联系是一种泛化联系,用带空心三角箭头的虚箭头表示(称为虚泛化符)。对于棒糖式接口的实现联系则用一条虚线表示。对象类可以通过依赖联系(虚箭头线)使用接口。此时可以标出构造型"<<use>>",也可不标。

5.6 高级对象类

    5.6.1 抽象类

    在UML中,可以用斜体的类名来表示抽象类,而不使用约束{abstract}。

wKioL1aoIcigi9DdAAAY3MSFXd4445.png

    5.6.2 模板对象类模板对象类又称参数对象类,量一个尚未完全具体说明的类。模板中提供参数表,利用参数表向模板传递信息可最终形成用户需要的具体类。参数可以是类,也可以是整数,布尔型等基本类型。由于给定不同的参数便可确定不同的类,所以模板能够说明许多类,故又称模板是一个用参数表示的类。

5.7 对象类图建模

    5.7.1 建立对象类图

    一般情况下,建立对象类图包含以下几个步骤:

  1. 研究和分析问题域,确定系统的需求。

  2. 发现、识别、确定系统中的类和对象,明确它们的含义和责任,确定属性和操作。

  3. 找出类之间存在的静态联系。要重点分析出类之间存在的一般与特殊、部分与整体关系,研究类之间的继承性和多态性,把类之间的这种联系用泛化、聚合和组合、关联、依赖等关联表达出来。

  4. 对已经发现的类之间存在的联系进行调整和优化,去除可能存在的命名冲突和功能重复等问题。

  5. 绘制对象类图并编制相应的说明。

    绘制好的对象类图不应过于复杂,图形元素一般不要超过9个,类图的大小一般以一张A4纸为宜。如果一张类图中图形元素太多,就应该按照类图的抽象层次分层绘制,同一个层次的类图按一个Use Case或一个子系统绘制。如果图形仍然过大,则再进行划分。

    5.7.2 类和对象建模中应注意的问题

    1. 模型视角(Perspectives)和粒度

    通常情况下,铿现实世界的问题域,建立对象模型和绘制对象类图可以从以下三个模型视角出发:概念视角、说明视角和实现视角。

    从概念视角出发,可以通过对象类来表现问题域的概念模型。在概念模型中不考虑软件实现方面的问题,因而它是独立于程序设计语言的。在系统的分析阶段一般从概念视角出发建立系统的分析模型。

    从说明视角出发,可以通过对象类图来表现软件的结构和接口,而不是软件的实现。在系统的设计阶段一般从说明视角出发建立系统的设计模型。

    按照实现视角绘制的对象类图体现在构建阶段产生的实现模型,它具体定义对象类及其实现。

    在建立对象模型时,可以采取由顶向下或由底向上的方式进行。顶层的对象类图是概念性的,下层的对象类图是上层对象类图的细化,增加了一些细节。最底层的对象类图是实现性的,一般可直接映射到程序设计语言。系统分析人员和高级程序员关心的是对象类的基本特性和它们之间的关系,他们只需要逻辑说明层的粒度较粗的对象类图。一般程序员关心的是对象类的属性、操作和联系的实现,需要的是实现层的粒度较细的对象类图。

    2. 例外建模(Exception)

    在UML中,可以把例外情况的处理用一个专门的类--信号来表达。当在某个操作的执行中出现例外的情况的条件成立时,就发送一个处理该例外情况的信号。

    对于系统中例外情况的建模可以按以下步骤进行:

    1.对每一个对象类和接口,找出可能出现的例外情况及其出现条件。

    2.将每一个例外情况用一个信号类来描述,类名前加上构造型<<exception>>。

    3.建立例外情况的层次结构,将一般性的例外情况置于顶层,把特殊性的例外情况置于底层。

    4.找出每一个操作可能出现的例外情况,将操作和它的例外情况的信号图标之间用一条虚箭头线连接,其上标出构造型<<send>>,表示操作的例外情况的“send”依赖。

    3.包建模技术

    当对大型系统进行建模时,经常需要处理大师的类、接口、构件、节点和图,这时就有必要将这些元素进行分组,即把那些语义相近并倾向于一起变化的元素组织起来加入同一包,这样方便理解和处理整个模型。