UML之深入浅出类图讲义

UML之深入浅出类图讲义

在面向对象方法中,类图是最重要的模型图,它描述了系统中各个对象的类型和它们之间存在的各种关系。建立类图是建模中最基本的任务。
一张类图应该注重表达系统静态结构的一个方面,这意味,若是系统较为复杂,可能要绘制多张类图。类图是描述类、协作(类或对象间的协作)、接口及其关系的图。

[提示]本讲义由于图片多达30几处,格式转换会有问题,故没有提交图片。请大家直接下载PDF图文阅读,下载地址:
http://download.csdn.net/detail/wojiushiwo987/9410741

OOA模型

4.1 类图的概念

类图(Class diagram)是最常用的UML图,显示出类、接口以及它们之间的静态结构和关系;我们常用类图描述系统的结构。

4.1.1类图

类图是描述类、协作(类或对象间的协作)、接口及其关系的图。与所有UML的其它图一样,类图可以包括注释、约束、包。图4-1是一个典型的类图。
类图中的关系包括:、继承关系(inheritance)/泛化关系(Generalization)、关联关系(Association)、聚合关系(aggregation)、依赖关系(Dependency)。

图4-1电子商务网站的对象模型

4.1.2类图的作用

类图常用来描述业务或软件系统的组成、结构和关系。我们通常通过下面三种方式使用类图:
(1)为系统词汇建模型
为系统的词汇建模实际上是从词汇表中发现类,发现它的责任。
(2)模型化简单的协作
协作是指一些类、接口和其他的元素一起工作,提供一些合作的行为,这些行为不是简单地将元素加在一起就能实现的。例如:当我们为一个分布式的系统中的事务处理过程创建模型时,我们不可能只通过一个类来表明事务是怎样执行的,事实上这个过程的执行涉及到一系列的类的协同工作。使用类图来可视化这些类和他们的关系。
(3)模型化一个逻辑数据库模式
我们常用类图设计数据库的蓝图。在很多领域,我们想把持久性数据保存到关系数据库或面向对象的数据库中。我们可以用类图为这些数据库模式建立模型。

4.1.3类图的组成元素

类图中的元素有类、接口、协作、关系、注释、约束、包。关系把类、协作、接口连接在一起构成一个图。注释的作用是对某些类和接口进行注释,约束的作用是对某些类和接口进行约束。

4.1.4对象与类的概念

(1)对象是具有明确语义边界并封装了状态和行为的实体,即它是系统中用来描述客观事物的一个实体,是构成系统的一个基本单位,由一组属性和作用在这组属性上的一组操作构成。
按照面向对象的封装和信息隐蔽原则,一个对象的属性和操作时紧密结合的,对象的属性应该只由这个对象的操作存取。
(2)类是对具有相同属性、操作、关系和语义的对象集合的描述, 也就是说它为属于该类的全部对象提供了统一的抽象描述。对象是类的实例。
一个类的所有对象具有相同的属性,是指所有对象的属性的个数、名称、数据类型都相同,但各个对象的属性值可以互不相同,并且随着程序的执行而变化。操作对于一个类的所有对象都是一样的,即所有的对象共同使用他们类的定义中给出的操作方法。
(3)类和对象的关系
①类是一组对象,这些对象具有共同的属性和共同的行为
②类是创建对象的模板
③类可捕获对象的本质
④类是对象的抽象,而对象则是类的实例,或者说是类的具体表现形式
如同一个模具与用这个模具铸造出来的铸件之间关系。根据实际需要,通过对具有相同性质的事物的抽象,构造出模具,再用模具生产出具有这样性质的铸件。

                          图4-2类和对象的关系

在面向对象方法中,通过对具有相同性质的对象的抽象,构造出类,进而使用类构造出系统模型;在系统运行时,又由类创建出对象。正是所创建的这些对象在计算机中的运行,完成了用户所要求的功能。

4.1.5 类的种类

1.抽象类
在进行类设计时,如果一些具体类具有相同的方法或属性,我们可以把这些相同的方法或属性从这些具体类中抽取出来,把它们封装到一个抽象类中,然后,通过扩展抽象类,重新定义这些具体类。
抽象类是一种不能直接实例化的类,也就是说不能用抽象类创建对象。
在UML中,抽象类和抽象方法的表示是将其名字用斜体表示。但是由于斜体字在草图中不容易表现,因此推荐用《abstract》构造型来表示。图4-7中列出这两种不同的表示方法。

图4-7 抽象类的2种表示方法
抽象类shape(图形)中定义三个方法,drew()、getarea()是抽象方法,getboundingarea()是具体方法。在squre(正方形)和circle(圆形)两个子类中,没有定义getboundingarea(),确定义了drew()和getarea()方法。
抽象类shape定义的draw()和getarea()是抽象操作,在不同的子类中,其实现方法是不同的,即,在square和circle类中,对上面两个抽象方法,有不同的实现。
2.主动类
从运行的角度来看,还有一种特殊的类-主动类,主动类的实例称为主动对象,一个主动对象拥有一个控制线程并且能够控制线程的活动,具有独的控制权。
例如,命令处理程序就是一个主动类的例子,它从外面接受命令对象,然后在自身的控制线程内执行命令。在第二章中,曾经说明UML1.0中主动类的表示方法(普通类的基础上加上粗边界),但是在UML2.0中修改了主动类的表示法(在类的两边加上垂直线)。
3.模版类
在注入c++这样语言中,提供了一种叫做参数化类(parameterized class)的机制,或叫做模版(template)。例如,我们需要一些能过处理整型、浮点型、字符串的数组,普通的做法是为它们各创建一个类,这三个类除了数据类型不同之外,其他的都是相同,但是仍然要定义三次。
模版就是用来解决这个问题,可以根据占位符或者参数来定义类,而不用说明属性、方法返回值和方法参数的实际类型。通过实际值代替占位符即可创建新类。这样,就可以采用如图4-8所示的设计方案。

图4-8 模板类
4.嵌套类
在诸如Java的语言中,允许你将一个类的定义放在另一个类定义的内部,这就是嵌套类,在Java中也称为内层类。嵌套类是声明在它的外层类中的,因此只能够通过外层类或外层类的对象对它进行访问 ,在UML中,可以采用一个描图标来表示这种关系,如图4-9所示。

图4-9 嵌套类表示法

4.2属性与操作

UML中,表示一个类,主要是标识它的名称、属性和操作。如图4-3所示,类由一个矩形表示,它包含3栏,在每栏中分别写入类的名称、类的属性和类的操作。

图4-3 Order类
用一个水平线划分成三个分栏的实线矩形表示类。在最上面的那个分栏放类名,中的分栏放属性列表,最下面的分栏放操作列表,每个属性和操作都各占一行,下图(a)给出的是表示一般类的符号。由于对象是类得实例,一个类的各个对象所拥有的操作都是相同的,因此对于对象只需描述对象名和其属性,下图(b)给出的是表示对象的符号。

1.名称
每个类都必须有一个有别于其他类的名称, 类名部分是不能省略的,其他组成部分可以省略。名称(Name)是一个文本串,表示方法有两种:
(1)简单名:如图4-3中的Order(订单),它就只是一个单独的名称。
(2)全名:也称为路径名,就是在类名前面加上包的名称,例如java::awt::Rectangel、businessRule::order等。
对于类的命名规范要求,由字符、数字、下划线组成的惟一的字符串即可。但在实际应用中,有一个普遍采用的命名原则:采用CamelCase格式(大写字母开头、混合大小写,每个单词以大写开始,避免使用特殊符号),尽可能避免使用缩写。
2.属性
属性描述了类的静态特征,在面向对象编程中,把属性表示为成员变量。例如,在图4-3所示的Order类中,列出了orderDate(下订单时间)、destArea(送货区域)、price(订单总价格)、paymentType(支付类型)四个属性,它们是用来描述每个具体的订单对象的。
在属性的前面有一个修饰,用来表示属性的可见性,属性的可见性一般都是private,这样才符合面向对象的“封装”思想。通常属性名的第一个字母是小写的。
3.操作
操作是类所提供的服务,是对象被要求执行的服务。通俗地说,操作就是定义了对象所能做的事情。在面向对象编程语言中,它通常表示为成员方法。对于操作的图示,有以下几点需要说明:
(1)操作名的命名规范也未硬性规定的,大家习惯采用和属性名相同的命名规则。
对于操作,也经常会提供可见性修饰,只是通常应该声明为public,否则它难以向其他类提供服务。
(2)操作在表示时可以只写出操作名,也可以将操作拥有的参数也写出来,即写成员方法的完整签名。
(3)属性和操作名之前可附加的可见性修饰符:
加号(+)表示public(共有的);
减号(-)表示private(私有的);
‘#’号表示protected(受保护的);
~号表示包范围的。
省略这些修饰符表示具有package(包)级别的可见性。 如果属性或操作名具有下划线,则说明它是静态的。
4.职责
职责指类承担的责任和义务。在矩形框中最后一栏中写明类的职责。如图4-4所示。

图4-4 职责的表示
5.约束
约束指定了类所要满足的一个或多个规则。 在UML中,约束是用花括号括起来的*文本。如图3-4所示。

图4-5约束的表示
举例如下:
其对应的类操作、实例操作的表示法为:
图4-6类图表示示例

4.3 类图中的关系

类不是孤立存在的,因此,类与类之间创建了一种关系。按照关系的性质,把关系分为4种,它们是泛化关系、关联关系、聚合关系、依赖关系。

图4-10 类关系
下面分别说明其语义。

4.3.1泛化关系

定义:如果类A具有类B得全部属性和全部操作,而且还具有自己特有的一些属性或者操作,则A叫做B的特殊类,B叫做A的一般类,A与B之间的关系称为继承关系。
继承关系又叫做一般—特殊关系,在UML中把继承关系称为泛化关系。
是从特殊元素到一般元素的分类关系称为泛化关系。模型元素可以是类、用例以及其他。表示法:继承可表示为从特殊类到一般类的一条实线,在一般类的那端有一个空心三角。如图4-11所示:

图4-11 泛化关系
继承是一种使用户得以在一个类的基础上建立新的类的技术。新的类自动继承旧类的属性和行为特征,并可具备某些附加的特征或某些限制。新类称作旧类的子类,旧类称作新类的超类。
继承的优点:能有效地支持软件构件的重用,使得当需要在系统中增加新的特征时,所需新代码最少。继承机制的强有力之处还在于它允许程序设计人员可重用一个未必完全符合要求的类,允许对该类进行修改而不至于在该类的其它部分引起有害的副作用。继承性是
面向对象程序设计语言不同于其它语言的最主要特点是其它语言所没有的。
结构 说明 语法
泛化 它是较一般类和较具体类之间的分类关系
①泛化:标识各个类之间的共同性。
②指明特化类(子类)的对象可取代泛化类(父类)的对象。
③是“is-a”关系。
详解泛化关系如下图所示:

图4-12 泛化关系(打印机)

4.3.2关联关系

1.基本概念
定义:如果一个类的对象与另一个类的对象之间有语义连接关系,那么这两个类之间的语义关系就是关联。
表示法:把二元关联表示成连接两个类符号的实线。在关联的实线上,可以给出关联的名称,可以在关联的端点上给出关联的一些性质。关联可以有方向,如果要限制关联的访问方向,就要在关联上加上一个表示方向的箭头。
如图所示:

关联是类之间的一种关系,在类实例化后,这种关系将落实到每一组具有这种关系的对象之间。例如,类“教师”和类“学生“之间存在着关系“指导毕业论文”,这种关系所表达的信息是:类“教师”和类“学生”之间存在着关系“指导毕业论文”,这种关系所表达的信息是:类“教师”的对象和类“学生”的对象之间存在一种联系,其语义是表明某个(些)教师为某个(些)学生指导毕业论文。至于谁给谁指导毕业论文,要到实现时才能确定,甚至要到系统交付使用后由用户指定。把类之间的这种静态关系称为关联。
把二元关联( binary association)表示成连接两个符号的实线。为了避免与其他图符号交叉,可以把实线划成折线。表示关联的实现的两个端点可以连接到相同的类或不同的类,但是端点是不同的,因此要在各个端点的实线上可以给出关联的名称。
如果没有对关联指定方向,从关联的任意一段都可以访问另一端,即通过关联的访问是双向的。如果要限制关联上的访问方向,就要在关联上加上一个表示方向的箭头。如下图所示:

单向关联的表示法示例
如上图所示,给定一个用户就能找到他可能拥有的口令,但反过来给定一个口令就不需要去找响应的用户。这种导向是单项性,就是通过“口令”类的那一端在关联线上加一个箭头来说明的。

2.多重性
如下图所示:

通常在关联的两端写有表示数量约束的数字或符号,把他们称为关联的多重性(multiplicity)。关联的另一端上的多重性是指,本段的一个对象所可能需要的另一端对象的个数。
上图所示含义:一名学生拥有一份或多份成绩单,一份成绩单只能被一名学生所拥有。
一个多重性描述的数量范围可由一系列的正整数区间来指明,各区间由逗号分开。区间的格式为:
下限 .. 上限
其中的下限和上限均可为正整数值,下限也可为0,上限也可为。如果多重性由单个的“”构成,那么它表明的范围为任意的正整数范围,它等价于0.. *。
示例:假设左类为A,给定A的一个对象a,右侧关联类为B
1 表示a 恰好与类B的一个对象关联;
0..1 表示a 最多与类B的一个对象关联;
1..* 表示a 与类B的一个或多个对象关联;
0..* 表示a 与类B的零个或多个对象关联。
如下图:

说明:一名教师可以是一个系的系主任,也可以不是任何系的系主任;一个系只有一名教师作为其系主任。
3.关联角色
在关联的每一个端点上可以有一个名字,用以表示与该关联的端点相连接的类所扮演的角色,把这个名字称为关联角色名。
通常用名词为关联的角色命名。如上图红色标记的关联角色为“任系主任”。使用关联角色有助于理解关联。
4.关联类
在应用当中,我们发现两个类之间具有多对多的关系,并且有些属性不属于关联两端任何一个类,例如,在某个应系统中有两个类:person(人)和institute(协会),显然person可以属于多个institute,而每个institute肯定会吸纳很多person。因此它们之间很显然就是一个多对多的关系。
如果要记录每个person在所属的institute所担任的职务,应该把这个职务属性放在哪个类中呢?这个属性既不属于person,也不属于institute。显然,这个属性应该放在关联类中(Role),如图4-12所示。

图4-12关联类Role

实际上关联类既是关联又是类,它不仅象关联那样连接两个类,而且可以定义一组属于关联本身的特性。
注意:只有关联每一端的对象是1:1对应时,才能创建关联类。
结构 说明 语法
关联 (association)是类之间的一种连接。是对象之间的长期关系。通常是双向的。
①识别类之后,需要识别关联
②如果类与类之间的联系是单向的,则称为单向关联(导航关联)
③多重性(multiplicity)定义有多少对象参与了某个关系
示例如下:

示例:“雇员为公司工作”

图4-13单向关系
关联关系是比较抽象的高层次关系,为了对关联进一步具体化,我们需要了解关联的属性。关联的属性包括名称,角色,多重性,限定,导航。
1)名称
可以使用一个动词或动词短语给关联取名,用来描述关联的性质。在描述关联时,关联的名称并不是必需的,在关联名和角色中选一即可。可以在关联上标识阅读方向的方向指示符,以消除阅读的歧义。
下面的例子表示,关联名称是”使用” ,即,用户使用计算机。

图4-14关联名称
2)角色
在关联关系中,角色表明了关联的每一端在关联中承担的职责,即,关联发生时,关联的每一端在关联中扮演的角色。角色的名称应该是名词或名词短语,以解释对象是如何参与关联的。如图4-15关联的角色。

图4-15关联的角色
学生在关联中,扮演的是学习者的角色;学校扮演的是教学者的角色。
3)多重性
多重性就是某个类有多少个对象可以和另一个类的单个对象关联。如图4-16所示。

图4-16关联的多重性
上图的多重性表示:一个学校可以有多个学生学习;一个学生可以到多个学校去学习,或不去任何学校学习。
4)导航性
导航性描述了源对象通过链接访问目标对象。箭头表明了导航的方向性,即,只有源对象才能访问目标对象,反之,目标对象不能访问源对象。如图4-17所示。

图4-17导航性
5)限定符
如果源对象到目标对象是1对多关联,为了在多个目标对象的集合中查找到需要的目标对象,我们必须在目标对象集合中,选一个唯一标识目标对象的查找键(限定符,从目标对象的属性中选择),它应该是目标对象中的某个属性,当然,也可以是表达式。

图4-18限定符
一个俱乐部(Club)可以有多个成员(Member),为了在成员集合(目标对象)上找到需要的对象,我们选择memberId作为查找关键字,即,限定符。

4.3.3聚合关系

基本概念:
聚合(aggregation)是表示整体的类和表示部分的类之间的“整体—部分”关系。一个类的对象,以另一个类的对象作为其组成部分,这样的对象之间具有“一部分”或“有一个”的语义。也可以理解为,一个类的定义应用了另一个类的定义。
组合(composition)是聚合的一种形式,一个部分类的对象在一个时刻至多属于一个整体类的对象,且整体类的对象管理它的部分类的对象。
组合关系仍然是整体与部分之间的关系,只是多了语义限制,故说它是聚合的一种形式。
在聚合关系中,把作为“整体”的类称为聚集,作为“部分”的类称为成分。
结构 说明 语法
聚合 一种特殊形式的关联,指定了聚合体(整体)和局部之间的关系
①共享聚合(空心菱形)意味着在组合端的多重性有多个。
②模拟“整体-局部”关系。
示例如下:

例如,大学由多个学院组成。

图4-19 聚合关系
结构 说明 语法
组合 一种特殊形式的关联。是一种整体和部分所属更强的聚集关系。每个部分只能属于一个整体。
①这是一种更强的聚合,表达了类与类之间更强的耦合
②组合的图形为实心菱形。
③容器负责创建和删除各个部分。

例如,窗口中的菜单和按钮不能离开窗口独立存在,因此,是组合关系。

图4-20组合关系

4.3.4依赖关系

定义:依赖是两个模型元素之间的一种语义关系,它表明对目标元素的改变可能需要改变该关系中的源数据。
依赖可表示为两个建模元素之间的虚箭头。在箭头尾部的模型元素(源元素)依赖箭头头部的模型元素(目标元素)。可以用放在双尖括号内的字符串标识箭头,如用况图中的《include》和《extend》。
表示两个或多个模型元素之间语义上的关系, 客户元素以某种形式依赖于提供者元素。 实际上,关联、实现和泛化都是依赖关系。 如图4-21所示。

图4-21 依赖关系
结构 说明 语法
依赖 如果一个类依靠另一个类的服务来完成其角色,则它们之间的关系称为依存关系
依赖关系指明两个或多个类之间的语义关系,尽管两个类之间没有明确的关联,一个类发生变化也会导致另一个类发生变化。

依赖关系可以细分为4大类:使用依赖、抽象依赖、 授权依赖、 绑定依赖。
(1)使用依赖
表示客户使用提供者提供的服务,以实现它的行为,下面都属于使用依赖的具体形式:
使用(《use》)
调用(《call》)
参数(《parameter》)
发送(《send》)
实例化(《instantiate》)
(2)抽象依赖
表示客户与提供者之间的关系,客户与提供者属于不同的抽象事物,具体依赖形式:
跟踪(《trace》)
精化(《refine》)
派生(《derive》)
(3)授权依赖
表达一个事物访问另一个事物的能力,具体依赖形式:
访问(《access》)
导入(《import》)
友元(《friend》)
(4)绑定依赖
绑定依赖属于较高级的依赖类型,用绑定模板以创建新的模型元素,具体依赖形式:绑定(《bind》)

4.4接口

在接口定义为一个类的对外可见的一组操作的描述符,它定义了类对外提供的服务。
一个类可以实现一个或者多个接口,也称类提供了一个或者多个接口。一个或多个类可使用一个或者多个接口,也称类依赖一个或者多个接口。
接口是一种类似于抽象类的机制,接口中的方法都是抽象方法。在UML中,接口有如图4-24所示的两种表示方法。

图4-24 接口的两种表示法
图标表示方法的优点是简单,它只适用于只有单个操作的接口和草图应用中。构造符号表示法是采用类(interface实际上是一种特殊的类)的方式表示,它的优点是可以添加多个抽象方法,具有更强的表示能力。
接口有两种表示方法:

图4-25用类表示的接口示例
上述的带空心箭头的虚线表示实现关系。上图中类“传感器”实现了“传感器接口”,类“警报器”使用接口“传感器接口”。

图4-26简化形式的接口示例

4.5如何建立对象模型

下面通过一个简单的例子来说明建立对象模型的过程。

4.5.1 问题陈述

小刘是一个爱书之人,家里各类书籍已过千册,而平时又时常有朋友外借,因此需要一个个人图书管理系统。该系统应该能够将书籍的基本信息按计算机类、非计算机类分别建档,实现按书名、作者、类别、出版社等关键字的组合查询功能。在使用该系统录入新书籍时系统会自动按规则生成书号,可以修改信息,但一经创建就不允许删除。该系统还应该能够对书籍的外借情况进行记录,可对外借情况列表打印。另外,还希望能够对书籍的购买金额、册数按特定时限、周期进行统计。

4.5.2 寻找分析类

我们以问题陈述为输入信息,采用“名词动词法”寻找分析类。名词动词法的主要规则是从名词与名词短语中提取对象与属性;从动词与动词短语中提取操作和关联。

1.找备选类
首先。可以逐字逐句地阅读上面那段需求描述,并将其中的所有的名词及名词短语列出来,可以得到备选类列表。
2.从备选类中筛选出候选类
并不是所有的备选类都是适合候选类,有些名词对于要开发的系统来说无关紧要。甚至不属于系统;而有些名词表述的概念则相对较小,适合某个候选类的属性。因此,需要对备选类进行一番筛选,将这些不适合的排除掉。
(1)“小刘”、”人”、”家里”很明显是系统外的概念,无须对其建模;
(2)而“个人图书管理系统”、“系统”指的就是将要开发的系统,即系统本身,也无须对其进行建模;
(3)很明显“书籍”是一个很重要的类,而“书名”、“作者”、“类别”、“出版社”、“书号”则都是用来描述书籍的基本信息的,因此应该作为“书籍”类的属性处理,而“规则”是指书号的生成规则,而书号则是书籍的一个属性,因此“规则”可以作为编写“书籍”类构造函数的指南。
(4)“基本信息”则是书名、作者、类别等描述书籍的基本信息统称,“关键字”则是代表其中之一,因此无需对其建模;
(5)“功能”、“新书籍”、“信息”、“记录”都是在描述需求时使用到的一些相关词语,并不是问题域的本质,因此先可以将其淘汰掉;
(6)“计算机类”、“非计算机类”是该系统中图书的两大分类,因此应该对其建模,并改名为“计算机类书籍”和“非计算机类书籍”,以减少歧义;
(7)“外借情况”则是用来表示一次借阅行为,应该成为一个候选类,多个外借情况将组成“外借情况列表”,而外借情况中一个很重要的角色是“朋友”—借阅主体。虽然到本系统中并不需要建立“朋友”的资料库,但考虑到可能会需要列出某个朋友的借阅情况,因此还是将其列为候选类。为了能够更好地表述,将“外借情况”改名为“借阅记录”,而将“外借情况列表”改名为“借阅记录列表”;
(8)“购买金额”、“册数”都是统计的结果,都是一个数字,因此不用将其建模,而“特定时限”则是统计的范围,也无需将其建模;不过从这里的分析中,我们可以发现,在该需求描述中隐藏着一个关键类—书籍列表,也就是执行统计的主体。
通过上面的分析,得到一个候选列表:
书籍 计算机类书籍 非计算机类书籍
借阅记录 借阅记录列表 书籍列表

4.5.3 确定类关系\

通过上面的工作,从需求描述中找到了6个相关的类,接下来就是确定类之间的关系。
1.确定类关系
可以发现“计算机书籍(itbook)”、“非计算机书籍(otheritbook)”与“书籍(book)”之间是继承关系;而“书籍列表(booklist)”是多个“书籍”组成的,“借阅记录列表(brrow list)”是由多条“借阅记录”组成的。这种组成关系使用于组合还有聚合关系呢?显然,由于本系统的“书籍”是可以独立于“书籍列表”而存在;“借阅记录”也是可以独立于“借阅记录列表”而存在,因此使用聚合更合适一些。还可以发现“借阅记录“和”“书籍”是关联的,离开“书籍”,“借阅记录”不存在意义。
为了反映和记录这些类之间的关系,可以使用UML中的类图将其记录下来,如图4-27所示。

图4-27 最初的分析类模型

2.给关联添加属性
上图没有表示出关联的细节信息(关联的属性没有标识出来)。
(1)确定关联的多重性
例如一本书可以有几条借阅记录,书籍列表指的是多少本书籍,这些问题需要进一步的进行多重性分析,并修改上面所示的类图。
因为是个人藏书,因此每本书都是唯一的,没有副本,要么被借出,要么未被借出,因此对于每一本书籍来说,要么只有一条借阅记录,要么没有借阅记录。
所有的书籍组成书籍列表,借阅记录刘表是由所有的借阅记录组成。
通过上面的分析,可以得到信息补充的类图,即可得到如图4-28所示的类模型。

图4-28 加入多重性的类图

如果系统较大,可以以上面的类图为基础,把关联度紧密的类合成一个包,以便更好的组织子系统。例如,在本例中可以将“书籍列表”、“书籍”、“计算机书籍”、"非计算机书籍“合成一个包,而将“借阅记录”、“借阅记录列表”合成另一个包。但本例比较简单,类相对较少,因此无须进行这样的合成。
(2)确定关联的导航性——类图中的诸如导航性,角色名,导出属性,限定符及约束等高级属性不是每个类模型都必须加入的。
在图4-27中,只有book和booklist之间的组合关系,brrowlrecord与borrowlist之间的组合关系、book与borrrecord之间的关联关系,这三个关系可能存在导航性。
组合关系显然已经将类的关系清晰化了,因此无须对其进行导航性描述。根据对需求的理解,book与borrowrecord之间,应该是一个双向链接。因为,当浏览书籍列表时,会希望看到某本书是否被借出;当有人归还时,希望能从借阅记录中关联到book。
(3)确定约束
根据用户需要,我们有两个地方可以用约束来体现:一是book对象创建之后就不能被删除,只能做修改,因此在book类边上加上了一条用*文本写的约束。二是一本书要么属于计算机类,要门属于非计算机类。因此要加一个“{xor}”约束。
(4)确定关联的限定符
由于这个系统是“个人图书管理系统”,因此特定的一本书只有一本,所以只能被借一次,因此对于一本书而言,只有一个Recordid与其对应,因此将添加一个Recordid限定符。把限定符加入图4-28中,再把类的职责(属性和方法)加入到类图后,得到的类图,如图4-29所示。
3.给类添加职责
当找到了反应问题域本质的主要类,并清理他们之间的关系之后,就可以为这些类添加相应的职责。类的职责包括以下两个内容:类所维护的信息(成员变量)和类提供的行为(成员方法)。
在本阶段将主要的成员变量和成员方法标识出来,以便更好的理解问题域。
书籍类:从需求描述中,可找到书名、类别、作者、出版社;同时从统计的需要中,可得知“定价”也是一个关键的成员变量。
书籍列表类:书籍列表就是全部的藏书列表,其主要的成员方法是新增、修改、查询(按关键字查询)、统计(按特定时限统计册数与金额)。
借阅记录类:借阅人(朋友)、借阅时间。
借阅记录列表类:主要职责就是添加记录(借出)、删除记录(归还)以及打印借阅记录。
通过上面的分析,我们对这些概念类有了更深入的了解,可以重新修改类,将这些信息加入原先的模型中。同时,把关联的属性加入类模型后,得到如图4-29所示的类图。
职责(属性,方法)的添加是一个循序渐进的过程,在类分析,类设计时都是逐步对类模型进行完善的。

图4-29 加入限定符和约束的类图

4.6 UML中类图实例

接口:空心圆+直线(唐老鸭类实现了‘讲人话’);
依赖:虚线+箭头(动物和空气的关系);
关联:实线+箭头(企鹅需要知道气候才迁移);
聚合:空心四边形+实线+箭头(雁群和大雁的关系);
合成/组合:实心四边形+实线+箭头(鸟和翅膀的关系);
泛化/继承:空心三角形+实线(动物和鸟的继承关系);
实现:空心三角形+虚线(实现大雁飞翔的接口);

UML类图

解释UML类图:
1.首先看“动物”矩形框,它代表一个类。该类图分为三层,第一层显示类的名称,如果是抽象类就要用斜体显示。第二层是类的特性,通常就是字段和属性。第三层是类的操作,通常是方法和行为。
注意前面的符号,‘+’表示public, ‘—’ 表示private, ‘#’表示protected.

2.“飞翔”矩形框表示一个接口图,它与类图的区别主要是顶端有《interface》显示,第一行是接口名称,第二行是接口方法。接口还有另一种表示方法,俗称棒棒糖表示法,就是唐老鸭类实现了“讲人话”的接口。

interface IFly interface Ilanguage 
{ { 
void Fly(); void Speak(); 
} }

3.动物,鸟,鸭,唐老鸭他们之间都是继承的关系,继承关系用空心三角形+实现来表示。

            4.“大雁”实现了“飞翔”接口。实现接口用空心三角形+虚线来表示。(注:下面的图中应为空心三角形)
class Bird:Animal class WideGoose:IFly 
{ { 
//继承动物类 //实现飞翔接口 
} }

5.企鹅与气候有很大的关系,企鹅需要“知道”气候的变化,需要“了解”气候规律。当一个类“知道”另一个类时,可以用关联(association)关系。关联关系用实线箭头来表示。

class Penguin :Bird 
{ 
private Climate climate;//在企鹅Penguin中,引用到气候Climate对象 
}

6.“大雁”和“雁群”这两个类。大雁是群居动物,每只大雁都属于一个雁群,一个雁群可以有多只大雁。所以它们之间就满足聚合(Aggregation)关系。聚合表示一种弱的“拥有”关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分。聚合关系用空心的菱形+ 实线箭头表示。

class WideGooseAggregate 
{ 
private WideGoose[] arrayWideGoose; 
//在雁群WideGooseAggregate类中,有大雁数组对象arrayWideGoose 
}

7.“鸟”和“翅膀”这两个类。鸟和翅膀似整体和部分的关系,并且翅膀和鸟的生命周期是相同的,在这里鸟和其翅膀就是合成关系。合成(composition)是一种强的“拥有”关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。合成关系用实心的的菱形+实线箭头来表示。另外,合成关系的连线两端还有一个数字“1”和数字“2”,,这被称为基数。表明这一端的类可以有几个实例,很显然,一个鸟应该有两支翅膀。如果一个类可能有无数个实例,则就用“n”来表示。关联关系,聚合关系也可以有基数的。

class Bird 
{ 
private Wing wing; 
public Bird() 
{ 
wing=new Wing(); 
//在鸟Bird类中,初始化时,实例化翅膀Wing,它们之间同时生成 
} 
}

8.“动物”、“氧气”与“水”之间。动物有几大特征,比如有新陈代谢,能繁殖。而动物要有生命,需要氧气,水以及食物等。也就是说动物依赖于氧气和水。它们之间是依赖关系(Dependency),用虚线箭头来表示。

abstract class Animal 
{ 
public bolism(Oxygen oxygen,Water water) 
{ 
} 
}

小结

本章描述了建模中最为核心的图—类图。详细说明了类图的概念,类的表示方法,类关系。
在此基础上,讲述了阅读类图的方法、技巧和相关知识。首先介绍了关系和多重性等基本内容,然后介绍了导航箭号,角色名称,导出属性,限定符和约束等增强部分的阅读方法,最后还讨论了与类图相关的高级概念。这些高级概念包括接口/抽象类、关联类、模板类、主动类、嵌套类等再分析、设计模型中经常会遇到的概念;另外还深入介绍了依赖关系和两种类型的对象;最后通过实例分析详细解读了类图的设计。

作者:铭毅天下
转载请标明出处,原文地址:http://blog.csdn.net/laoyang360/article/details/50545582

如果感觉本文对您有帮助,请点击‘顶’支持一下,您的支持是我坚持写作最大的动力,谢谢!

作者:铭毅天下
来源:CSDN
原文:https://blog.csdn.net/laoyang360/article/details/50545582
版权声明:本文为博主原创文章,转载请附上博文链接!

上一篇:CHSNS#1.x 源代码包说明


下一篇:【愚公系列】2021年12月 二十三种设计模式(九)-装饰者模式(Decorator Pattern)