您的位置:首页 > 其它

UML核心技术学习(四)

2007-10-16 00:55 267 查看

第五章 静态建模:类图和对象图

用面向对象的方法处理实际问题时,需要建立面向对象的模型。构成面向对象模型的基本元素有类(class)、对象(objects)、类与类之间的关系等

4.1 类和对象

所谓对象就是可以控制和操作的实体,它可以是一个设备,一个组织或一个商务。类是对象的抽象描述,它包括属性的描述和行为的描述两个方面;属性描述类的基本特征,行为描述类具有的功能,也就是对该类的对象可以进行哪些操作;对象是类的实例化,所有的操作都是针对对象进行的
构建面向对象模型的基础是类、对象和它们之间的关系

4.2 类图

类图是用类和它们之间的关系描述系统的一种图示,是从静态角度表示系统的,因此类图属于一种静态模型。类图是构建其他图的基础,没有类图,就没有状态图、协作图等
类图中允许出现的模型元素只有类和它之间的关系

4.2.1 定义类

所定义的类通常要有这样两个特点:一是使用来自问题域的概念,二是类的名字用该类实际代表的涵义命名
l 有没有一定要存储或分析的信息?如果存在,那么该信息可能就是一个类
l 有没有外部系统?如果有,外部系统可以看作类,该类可以是本系统所包含的类,也可以是本系统与之交互的类
l 有没有模块、类库、组件等?
l 系统中是否有被控制的设备?
l 有无需要表示的组织机构?
l 系统中有哪些角色?

4.2.2 名字、属性和操作

属性有不同的可见性(visibility),利用可见性可以控制外部事物对类中属性的操作方式,有三种:公有的(public)、私有的(private)和保护的(protected)
在类图中,(+)表示公有的,(-)表示私有的,如果没有表示未定义

类的属性中还可以有一种能被该类的所有对象共享的属性,称之为类的作用域属性(class-scope attribute),也称作为类变量(class variable)
描述属性的语法: 可见性 属性名 : 类型名 = 初值 {性质串}

Java语言实现图4-6如下:

public class invoice
{
public double amount;
public Date data=new Date();
public String customer;
public String specification;
public String administrator=”unspecified”;
static private int number_of_invoices=0;

public invoice() //构造函数
{ //部分初始化工作可在此进行
number_of_invoices ++;
}
//类的其他操作方法写在这里
}

存取或改变属性值或执行某个动作都是操作,操作说明了该类能做什么工作。类将数据和对数据进行处理的函数封装起来,形成了一个完整的整体。
描述操作的语法为:可见性 操作名(参数表) : 返回值类型 {性质串}
操作可以看作是类的一个接口,通过该接口实现内、外信息的交互。

4.2.3 基本类型的使用

4.3 关系

类与类之间通常有关联、通用化(继承)、依赖和精化等四种关系

4.3.1 关联关系

关联用于描述类与类之间的连接,也是对象与对象之间的关联;如果某两个类的对象之间存在可以互相通信的关系,或者说对象双方能够感知另一方,那么这两个类之间就存在关联关系。
根据不同的含义,关联可以分为普通、递归、限定、或、有序、三元关联和聚合

4.3.1.1 普通关联

最常见的一种关联,只要类与类之间存在连接关系就可以用普通关联表示。

表示“某作家使用计算机”,黑三角的尖角指明这个关联只能用在尖角所指的类上;如果类与类之间的关联是单向的,称为导航关联;

表示“人可以拥有0至多个小汽车”,只有箭头所指的方向上才有这种关联关系,上图表明了人拥有小汽车,但是小汽车被人拥有的情况没有表示出来,其实普通关联是导航关联的一种特例;
在类图中图示关联中的数量关系—重数,表示数量关系:
0..1 表示零到一个对象 0..*或* 表示多个对象 5..17 表示5到17个对象
如果图中没有明确表示,那么就是1

上图表示:人可以拥有多辆小汽车,小汽车可以被1至多个人拥有
再如下图:

表示:保险公司有0或多个保险合同,这些合同与1个或多个客户有关;客户有0或多个保险合同,这些合同都与1个保险公司有关;保险合同位于一家保险公司和一个或多个客户之间,用它建立保险公司和客户之间的保险关系;保险合同用0或1个保险单表示,也就是合同的书面表示;一个保险单表示一份保险合同
多对多的双向关联,可以转化成两个一对多的关联来实现

4.3.1.2 对象图

类图表示类和类之间的关系,对象图则表示在某一时刻这些类的具体实例和这些实例之间的具体连接关系,其实表达对象图和类图几乎没有什么区别,只是名字下面有下划线

4.3.1.3 递归关联

如果一个类与它本身有关联关系,那么此关联称为递归关联(recursive association),递归关联指的是同类的对象之间语义上的连接。

4.3.1.4 关联中的角色

任何关联关系中都涉及到与此关联有关的角色,也就是与此关联相连的类中的对象所扮演的角色。引入角色的好处是:指明了类和类的对象之间的联系(CONTEXT),注意,角色名不是类的组成部分,一个类可以在不同的关联中扮演不同的角色

人在“驾驶”这个关联关系中,人扮演“驾驶员”司机的角色,车的所有权可由汽车公司扮演

人在“结婚”这个递归关系中,一个人扮演丈夫,另一个人就扮演妻子,如果没有结婚,那么这些角色也就不能应用了

4.3.1.5 限定关联

限定关联用于一对多或多对多的关联关系中。在限定关联中,使用限定词将关联中多的那一端的具体对象分成对象集。限定词可以理解为一种关键词,用关键词把所有的对象分开。利用限定关联可以把模型中的重数从一对多变成一对一

从油画类到图画类的关联,图画用它的ID号表示

4.3.1.6 或关联

所谓或关联就是对二个或更多个关联附加的约束条件,使类中的对象一次只能应用于一种关联关系

人与保险合同的关联关系不能同一般公司与保险公司的关联关系同时发生

4.3.1.7 有序关联

对象与对象之间的连接可以具有一定的次序,就像应该把窗口安排在屏幕之上一样

4.3.1.8 关联类

与一个关联关系相连的类,称作关联类。关联类并不位于表示关联关系的直线两端,而是对应一个实际的关联,用关联类表示该实际关联的一些附加信息

队列就是电梯控制器类与电梯类的关联关系上的关联类。电梯控制器通过读取队列信息,选择一个合适的电梯为乘客服务,关联类也有属性、操作和关联

4.3.1.9 三元关联

类与类之间的关联关系,不仅限于两个类之间,多个类之间也可以有关联关系。如果有三个类之间有关联关系,则称之为三元关联

扮演保险客户角色的“人”可以有0至多个保险合同,每个保险合同都与一家保险公司有关,保险公司扮演着承保者的角色,人和保险合同通过0或1个保险单建立三元关联

4.3.1.10 聚合(aggregation)

聚合是关联的特例。如果类与类之间的关系具有“整体与部分”的特点,则把这样的关系称为聚合。

识别聚合关系的常用方法是寻找“由……构成”、“包含”、“是……的一部分”,这些字句很好地反映了相关类之间的“整体—一部分”关系
聚合还有二种特殊的聚合方式,共享聚合、复合聚合
如果聚合关系中的出于部分方的对象同时参与了多个处于整体方对象的构成,则该聚合称为共享聚合,一般做为整体方的重数不是1,那么就是共享聚合,它是一个网状结构的关联关系

如果构成整体类的部分类,完全隶属于整体类,则这样的聚合就是复合聚合,也就是说,如果没有整体类则部分类也没有存在的价值,部分类的存在是因为有整体类的存在;整体方的重数必须是0或1,它是一个树状结构的关联关系

复合聚合的实现方式一般是将部分类中的对象作为整体类的成员对象(member object),将部分类封装(encapsulating)在整体类中

4.3.2 通用化

一个类(通用元素)的所有信息(属性和操作)能被另一个类(具体元素)继承,继承某个类的类中不仅可以有属于自己的信息,而且还拥有了被继承类中的信息,这种机制就是通用化。
UML中的通用化是通用元素和具体元素之间的一种分类关系。引入通用化的好处在于由于把一般的公共信息放在通用元素中,处理某个具体特殊情况时只需定义该情况的个别信息,这样就只需要定义新扩充或更改的信息,旧的信息可以不必修改(仍可继续使用)。
通用化用于类、用例等各种模型元素,注意:通用化针对类型,而不针对实例,比如:一个类继承另一个类,但一个对象不能继承另一个对象
通用化分成普通通用化和受限通用化

4.3.2.1 普通通用化

没有具体对象的类称作抽象类,抽象类一般做为父类,用于描述其它类(子类)的公共属性和行为(操作)。比如交通工具类,很难想象它的具体实例,但是它描述了交通工具的一般特征,加上{abstract}标记

抽象类一般都带有抽象的操作,抽象操作仅仅用来描述该抽象类的所有子类应有什么样的行为,抽象操作只标记出返回值、操作的名称和参数表,关于操作的的具体实现细节并不详细写出来,而是由继承抽象类的子类实现;这样,子类可以重新定义父类的操作,但重新定义的操作的标记(返回值、名称和参数表)应和父类一样

4.3.2.2 受限通用化

给通用化关系附加一个约束条件,进一步说明该通用化的使用方法或扩充方法,这样的通用化关系称为受限通用化。预定义的约束有四种:多重、不相交、完全和不完全

多重继承指的是,子类的子类可以同时继承多个上一级子类

与多重继承相对立的是不相交继承,即一个子类不能同时继承多个上一级子类,一般不做特别声明,一般的继承都是不相交继承
完全继承指的是父类的所有子类都被穷举完毕,不可能再有其它的未列出的子类存在

不完全继承与完全继承相反,父类的子类并不是无一遗漏地列出,而是随着问题不断地解决,不断地补充和完善,也正是这一点为日后系统的扩充和维护带来极大的方便。默认一般是不完全继承

4.3.3 依赖和精化的关系

依赖关系描述的两个模型元素(类、组合、用例等)之间的语义上的连接关系。其中一个模型元素是独立的,另一个模型元素是非独立的(依赖的),它依赖于独立的模型元素,如果独立的模型元素发生改变,将会影响依赖该模型元素的模型元素。

比如,某个类中使用的另一个类的对象做为操作的参数,则这两个类之间就具有依赖关系,类似的依赖关系还有一个类存取另一个类中的全局对象,以及一个类调用另一个类中的类作用域操作。
精化关系用于表示同一事物的两种描述之间的关系。对同一事物的两种描述建立在不同的抽象层上。精化关系常用于模型化表示同一事物的不同实现

精化用于模型的协调。

4.4 约束和派生规则

UML中的规则称为约束和派生。约束用于限制一个模型,派生用于描述某种事物产生的规则。关联关系可以被约束,也可以派生
如果一个关联是另一个关联的子集,则它们之间就会存在约束关联

派生是由现有的关联关系衍生而来,派生的关联名称前加一条斜线

出租公司和很多客户有租车合同,这里面有些人很重要,于是在公司和客户之间直接派生出“/VIP客户”的关联关系
属性也可以被约束和派生,比如约束属性:

+status: Status = unpaid {unpaid, paid}
+color: Color = red {red, green, yellow}
-administrator: String = “wwcd”

派生属性一般是由其它属性通过某种方式计算得来

通用化关系只有约束,没有派生,四种约束(多重、不相交、完全和不完全)
对角色的约束为了防止一个对象所扮演的多个角色连在一起,当然对时间也有约束
UML使用五种语法机制表示这些约束和派生规则(见书第四章30页)

4.5 接口

接口通常被描述为抽象操作,也就是只用标识(返回值、操作名称、参数表)说明它的行为,而真正实现部分放在使用该接口的元素中,这样,应用该接口的不同元素就可以对接口采用不同的实现方法。接口的具体实现过程、方法,对调用该接口的对象是透明的

4.6 包

包(package)是一种组合机制,把各种各样的模型元素通过内在的语义连在一起成为一个整体就叫做包。包通常用于对模型的组织管理,因此有时将包称为子系统(subsystem)。包拥有自己的模型元素,包与包之间不能共用一个相同的模型元素。
包能够引用来自其它包的模型元素,当有引用发生,那么包与包之间就建立了关系,它们之间允许建立的关系有依赖、精化和通用化

包与聚合很相似,如果一个包有模型元素构成的(拥有自己的内容),那么该包是复合聚合;如果一个包从其它的包中引用模型元素,该包是共享聚合

包的可见性除了公有、私有、保护外,还有一种是实现。实现可见性与私有可见性很相似,但是有依赖关系的包可用。如果一个包有实现可见性,则不允许其它包引用该包(即无依赖关系)
包也可以有接口,接口与包之间用实线相连,接口通常由包中的一个或多个类实现

4.7 模块

模块(templet)是一个尚未完全具体说明的类。模块中提供参数表,利用参数表向模块传递信息可最终形成用户需要的具体类。由于给定不同的参数便可确定不同的类,所以模块能够说明许多类,故又称模块是一个用参数表示的类

4.8 模型质量

模型要抓住各个重要方面,其次,模型要易于通信,具有明确的目标,易于维护,保证一致性和完整性等
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: