UML _ 类图
概述
定义
类图(Class Diagram)是用于显示一组类、接口以及它们之间关系的图。
类图用于对系统中的各种概念进行建模,并描绘出它们之间的关系,主要通过系统中的类以及类之间的关系来描述系统的静态结构
。
主要模型元素:
- 类
- 接口
- 关系(依赖、泛化、关联和实现)
- 其他:包、注解等。
注意
类图是最复杂的图
作用:
-
对系统词汇建模:
识别问题域的实体并进行抽象,用类图详细描述抽象及其执行的职责。 -
对简单协作建模:
协作是由一些协同工作的类、接口和其他模型元素所构成的一个整体;通过类图可以将简单的协作进行可视化和表述。 -
对逻辑数据库模式建模:
通过类图可以为数据库的逻辑设计建立模型。E-R图只针对数据,类图则更进一步,还可以对行为建模。
类
类是对一组具有相同属性、操作、关系和语义的事物的抽象。
确定类:
类一定是个实体,因此可以在数据库建立表的实体,就可以确立为类。
类不可以太宽泛,比如“物体”这类词不能用
组成:
-
名称(Name)
就是名字,不可省略。 -
属性(Attribute)
类的静态特性 -
操作(Operation)
类的动态特性或行为特征
表示:
在UML中,类通常表示为一个三栏矩形,顶部显示类名,中间显示类的属性,底部显示类的操作。
类的组成
名称(Name)
每个类都必须有一个区别于其他类的名称(类名唯一),类名部分不可省略。
组成:
-
简单名:只是一个单独的名称
不可省略
例如:Student -
路径名(限定名):在类名前面加上包的名称
可省略,一般类和图处于不同包下才使用
有两种表示方法: Printer from Office 和 Office :: Printer
命名规范:
-
由字母、数字、下划线、汉字组成的惟一的字符串,不能使用特殊符号。
-
正体字说明类是可被实例化的,斜体字说明类为抽象类。
命名建议:
-
采用大驼峰式(Upper Camel-Case)命名法:大写字母开头、大小写混合,每个单词首字母大写。
-
尽可能避免使用汉字和缩写形式。
-
尽可能使用业务领域中的术语,见名知义,并尽可能明确、简短、无歧义,以便于开发人员与用户之间的相互理解和交流。
-
一般而言,类的名字是名词。 且避免使用抽象、无意义的名词。
属性(Attribute)
属性是已被命名的类的静态特性,它描述了该特性的实例可以取值的范围。
属性是类的对象可能包含的数据或状态的抽象。
注意:
在泛化关系中,父类中可以被子类继承的属性和操作,在子类中不再添加。
表示语法:
[可见性] 属性名 [:类型] [多重性] [=初始值] [{特性串}]
可见性
描述该属性是否能被其他类引用。
关键字 | 符号 | Rose符号 | 语义 |
---|---|---|---|
public | + | ![]() |
允许在类的内部和外部访问 |
private | - | ![]() |
仅允许在本类中访问 |
protected | # | ![]() |
允许本类及其子类访问 |
package(Rose中Implementation ) | ~ | ![]() |
仅允许在定义的包中访问 |
属性名
-
建议采用小驼峰式(Lower Camel-Case)命名法:
第一个英文单词小写,其余的单词首字母大写。 -
如果属性名带下划线,则表示静态属性(类变量),能被该类的所有对象共享
属性类型:类似数据类型
属性的类型决定了该属性的所有可能取值的集合,。
可以是编程语言预定义的类型,也可以是用户自定义的类型。
多重性:类似数组
表示为一个包含于方括号中的数字表达式,位于类型后。
例如:
nums:int[1..10]
(两个点)
nums:int[10]
(两个点)
初始值
指定创建该类对象时一个属性的默认值,可以简化类实例化时的初始化工作和保护系统完整性。
特性串
指定关于属性的附加信息,即对属性性质的约束。
一个属性可以有多个特性串。
表示:
每个特性串要使用大括号括起来。
常见类型
UML2中定义了static(静态)、ordered(有序)、readOnly (只读/常量) 、unique(唯一)、derived(衍生) 、ID(标识/主键)等;也可以自定义特性串。
例如:PI:double=3.14159
操作(Operation)
操作是类的动态特性或行为特征,它是对一个对象所做的事情的抽象,并由该类的所有对象共享。
注意
-
类的操作是依赖其属性的,也就说,类的操作需要和类属性相关。
-
在泛化关系中,父类中可以被子类继承的属性和操作,在子类中不再添加。
表示:
[可见性] 操作名称 ( [参数列表] ) [:返回类型] [{特性串}]
例子:
可见性: 同属性
操作名称
- 由描述类行为的动词或动词短语构成,命名规则与属性相同。
- 对操作名添加下划线修饰表示静态操作。
参数列表
参数列表是可选的,也可以有默认值。
参数的方向表示了操作调用时,该参数传递值的方向。
取值 | 方向 | 说明 |
---|---|---|
in | 输入参数 | 不能对它进行修改 |
out | 输出参数 | 为了向调用者传递信息,可以对它进行修改 |
in out | 输入参数 | 等价于返回参数和in参数,可以对它进行修改 |
返回类型
任意有效数据类型(系统类型、自定义类型、void)
注意:
括号不可省略
特性串(不常用)
指定关于操作的特殊性质或约束要放在大括号{ }中。
UML定义了以下几种可以用于操作的特性,也可以自定义特性。
- abstract(抽象)、
- static (静态) 、
- leaf (叶子)
- isQuery (查询) 、
- sequence (顺序/返回多值且构成有序包)
- ordered (返回多值且有序)
- unique (返回多值且无重复)等;
职责、约束和注解(一般不用)
三者都不常用
职责(Responsibility)
指的是对该类的所有对象的相同的属性和操作共同组成的功能或服务的抽象(即该类负责什么事情)。
类的职责一般在非正式类图中使用,在类的下方增加一栏;类的职责只是一段或多段文本描述,并不是必须的。
职责主要用于交互图。
识别类的职责
设计原则: 低耦合、高内聚等。
低耦合高内聚原则:
- 耦合指的是模块间的相互关系,而内聚指的是模块内部各元素的关系。
- 模块间的关系越松散越好,而模块内部的关系越紧密越好。
约束(Constraint)
制定了该类要满足的一个或多个规则,使用关联关系时,经常使用约束,定义附加于关联关系之上的限制条件。
约束用连接两个关联路径的虚线表示,并带有大括号括起来的约束字符串。
注解(Note)
为类的添加更多的描述信息。
类的特殊类型(Type)
普通类是一个完善的功能类,可以直接产生实例化对象。
除了常见的的普通类,还有一些特殊的类。
- 抽象类
- 模板类
- 关联类
这些类不能产生实例化对象。
抽象类(Abstract Class)
抽象操作:
缺乏实现的操作。
抽象类
包含抽象操作的类是抽象类。
特点
-
抽象类是不完整的,不能被直接实例化,不能创建一个属于抽象类的对象。
-
抽象类可以有父类和子类
表示:
将类名和操作名用斜体修饰 或者用构造型来表示。
例
模板类(Parameterized Class)<泛型>
对应概念:C++中的模板与Java中的泛型。
模板类是指带有一个或多个未绑定的形式参数的类。
模板类根据占位符或参数来定义类,而不用说明属性、方法返回值和方法参数的实际类型。
在编译时把模板参数绑定到不同的数据类型,从而产生不同的类。
使用
- 根据占位符或参数来定义模板类,
- 使用带有
<<bind>>
构造型的依赖关系,通过实际值代替占位符或参数即可创建新类。
例
▲ 关联类(Association Class)
具有类的特性的关联关系,称为关联类。
在应用当中,如果发现满足以下两点,就可以创建一个关联类。
- 两个类之间具有多对多的关系,
- 有些属性不属于关联两端任何一个类
注意:
-
关联类的属性也要是私有的
,除了接口必须公开,其余一般就是私有。 -
实际上,关联类既是关联又是类,不仅象关联那样连接两个类,而且可以拥有类的特性——属性和操作。
作用:
通过关联类可以进一步描述关联的属性、操作及其他信息。
表示
关联类在UML中被表示为一个类符号,并通过一条虚线连接到关联路径。虚线上没有修饰内容。
类的构造型(StereoType)
构造型 是UML体系结构中的一种扩展机制,其目的是基于一个已存在的模型元素再重新定义一个新的模型元素。
一般表现形式为用“<<”和“>>”括起的名称
常用的类的构造型有:
<<Actor>>
- 参与者<<boundary>>
- 边界类<<entity>>
- 实体类<<control>>
- 控制类
分析类
<<boundary>>
、<<entity>>
和<<control>>
三种构造型被称为分析类。
分析类代表系统的原型类,业务需求通过分析类逻辑化,形成概念模型。
作用:
分析类是跨越需求到设计实现的桥梁,在从业务需求向系统设计的转化过程中起到重要作用。
分类
<<boundary>>、<<entity>>、<<control>>
构造型分别表示三种分析类——边界类、实体类、控制类。
边界(Boundary)类
边界类位于系统与外界的交界处,承担系统与外界的信息交互功能。
常见边界类:
如窗体、对话框、报表、与外部设备或系统交互的类等。
识别:
边界类可以通过用例确定,因为参与者必须通过边界类参与用例。
表示:
例子:
实体(Entity)类
实体类描述要保存到持久存储体中的信息。
类及其属性最终可能映射成数据库中的表以及字段。
识别:
实体类可以从现实中存在的客观事物,以及需要持久存放的信息两方面来发现。
表示:
例子:
控制(Control)类
控制类负责协调其他类工作和控制总体逻辑流程。
以委托责任的形式向其他类发出消息。
表示:
例子:
接口(Interface)
当接口为棒糖图时,能否定义属性和操作?(能)``当接口为棒糖图时,能否定义属性和操作?(能)
接口(Interface)是一个被命名的一组操作的集合,用于描述类或组件的一个服务。
接口主要定义操作签名,不包含属性和操作实现;实现留给实现该接口的类、构件或子系统去完成。
注意:
接口的所有内容都是公有的
。- 接口不包含属性和操作。
目的:
将规格说明和实现相分离。
接口间的关系
关联、依赖、泛化、实现
命名:
接口名称建议以大写字母“I”作前缀,与类相似,也有简单名和路径名两种形式。
分类及其表示
接口有两种表示方法:
- 棒糖图
- 带有
<<interface>>
构造型的类符号
两者关系:
棒糖图:只展示系统的供需接口可以使用
当实现细节是,需要画成类的符号。
分类:
注意:供给接口和需求接口是相对的
供给接口- 实现关系
供给接口是指:组件为其他组件提供服务的操作的集合。
供给接口只能向其它类(或构件)提供服务。
表示:
在棒糖图中用小圆表示
下图中Payment对IPay就是供给(接口)
需求接口- 依赖关系
需求接口是指:组件向其他组件请求相应服务时要遵循的接口。
需求接口表示类(或构件)使用其它类(或构件)提供的服务。
表示:
在棒糖图中用半圆表示
下图中的User对IPay就是需求(接口)
常见用途:
接口经常用于对软件构件(Component)的接缝来建模。
接口设计要求:
-
是简单而完整的
提供对于详述一个单一服务必要而充分的所有操作。 -
是可理解的
为使用和实现接口提供足够的信息,而不必考查现有的应用 或实现。 -
是可访问的
为指导用户寻找关键特性提供了信息,而不至于陷入大量的 操作细节。
关系
小结
一共有四种基本关系
类与类之间的关系最常见,通常有3种:
- 关联(Association)
- 泛化(Generalization)
- 依赖(Dependency)
类与接口之间的关系,一般有两种:
- 实现(Realization)-供给接口
- 依赖(Dependency)-需求接口
接口之间可以有关联和泛化关系,但较少用。
关联(Association)关系
定义
关联关系表示对象之间的结构关系,指出了一个事物的对象与另一个事物的对象之间的语义上的连接。
分类:
关联可以分为单向关联、双向关联。
关联关系靠近类的连接点被称为关联端,有名称、角色、可见性、多重性等特性。
分类
一元关联(自身关联)
一个类与自身的关联
二元关联
两个类之间的关联,最普通、最常用。
N元关联
Rose、SU等工具不能直接表示N元关联;EA可以表示。
是在3个或3个以上类之间的关联,用菱形向外引出关联路径。
不建议使用N元关联,大多数N元关联经过细致分析,都可转化成二元关联。
特性
除了连接类元素的关联路径之外,关联还有以下可选的特性:
- 名称
- 角色(role)
- 多重性(multiplicity)
- 构造型(stereotype)
- 导航性(navigation)- 箭头指向
- 限定符(qualifier)
- 约束(constraint)
名称
一般使用一个动词或动词短语来命名关联。
还可以在关联上标识阅读方向指示符,以消除阅读的歧义。
角色(一般隐含在类名上)
是指在关联关系中,一个类通过关联对另外一个类所表现出来的职责。
如果在关联上没有标出角色名,则隐含的用类名作为角色名。
多重性
是指在关联关系中,一个类的一个实例与另一个类的多个实例相关。
注意: 多重性是双向的
表示形式:minimum..maximum
注意: \(*和n\)都表示有多个对象
常见多重性
表示法 | 说明 | 表示法 | 说明 |
---|---|---|---|
0 | 表示0个对象 | 0..1 | 表示0- 1个对象 |
n | 表示n个对象 | 0..n | 表示0-n个对象 |
* | 表示许多对象 | 0..* | 表示0-n个对象 |
构造型
在关联关系中,也可以根据具体的语义设置一些构造型。
导航性
导航性根据方向不同,分为单向关联和双向关联。
注意: 需要分别设置两端的导航性,只不过两端都为true,将箭头隐藏。
限定符(qualifier)
限定符定义了被参考对象的一个属性,并可以将该属性作为直接访问被参考对象的关键字。
当需要使用某些信息作为关键字,来识别对象集合中的一个唯一对象时可以使用限定符,使用限定符的关联被称为受限关联。
表示:
注意:
-
限定符会影响关联的多重性。
-
限定符用于解决查找问题
约束(一般不用)
约束可以定义附加于关联关系之上的限制条件。
表示:
约束用连接两个关联路径的虚线表示,并带有大括号括起来的约束字符串。
分类
ordered:有序的
frozen:冻结的
xor:互斥的
可以用自然语言描述
表示
聚合和组合
关联关系有两种非常重要的特殊形式:
- 聚合(Aggregation)关系
- 组合(Composition)关系
用于表示整体与部分的关系
聚合关系
聚合(聚集)描述的是部分和整体关系的关联,描述了“has a”的关系。
部分可独立于整体而存在,是松散
的关联关系。
聚合(聚集)就像计算机和它的外围设备:
计算机只是很松散地和外部设备关联;
外围设备可有可无;
外围设备可以被其它计算机所共享。
表示
组合关系
组合(组成)关系是更强形式的聚合,描述了“contains a”的关系。
整体与部分一般具有同样的生存期,部分完全依赖于整体。
整体唯一地负责处理它的部分,包括创建和销毁。
组合(组成)就像是树和树叶:
一片树叶只能被一棵树所拥有;
一片树叶不能由几棵树所共享;
当树死去时,它的树叶也随之死去。
要求
-
在某一时刻,部分类的实例 只属于一个整体类的实例(比如桌腿和桌子);
-
不允许部分类游离于整体之外。
代码中的表现就是:一个类是另一个类的成员变量的数据类型
表示
异同点
相同点
都是描述部分与整体关系的特殊关联。
不同点
聚合松散,组合紧密。
-
一个部分事物对象可以属于多个聚合对象,但一个部分事物对象仅能属于一个组合对象。
-
聚合的对象生命周期可以不同,但组合对象则是同存同亡。
泛化关系
【注意】在泛化关系中,父类中可以被子类继承的属性和操作,在子类中不再添加。
泛化
泛化就是指一般化的过程。
也就是将一组对象相同的属性和操作做 抽象形成一个类。
一般描述的类被称作父类,特殊描述的类被称作子类。
注意:
-
接口之间也可以存在泛化关系(子接口与父接口)。
-
泛化可能跨越多个层次。一个子类的父类也可以是另一个父类的子类。
-
泛化关系描述的是“is a kind of”的关系。
-
继承是泛化的反操作
表示:
箭头:子类指向父类
例如:
可以描述为:
- Horse类继承Mammal类
- Mammal类泛化Horse类
泛化关系特点:
- 特殊事物完全符合一般事物;
- 在一般事物出现的地方,能够替换成特殊事物;
- 通过从特殊事物泛化或从一般事物特化可以创建泛化层次。
用途
- 自底向上的实例替换
可以使得子类的实例用于任何父类被声明使用的地方,实现多态。
尽管每个子类的实现方法不同,但外界调用方式完全一样。
例子:
- 自顶向下的成员继承。
可以让子类共享父类的属性和操作,实现继承。
public、protected属性和操作可被继承。
继承的方式有两种:单继承( C#、Java )和多继承(C++)。
例:
依赖和实现
类与接口可构成 依赖和实现 关系。
类 依赖 供给接口
类 实现 需求接口
依赖(Dependency)关系
依赖(Dependency)关系表示使用关系。
使用地方:
- 两个类之间
- 类与接口之间
要求
类A使用类B的信息和服务,并且提供者类B的变化可能会影响到客户类A。
常见分类
- 客户类的操作使用提供者类的对象 -
使用<<use>>
- 客户类的操作调用提供者类的操作 -
调用<<call>>
- 客户类的操作需要提供者类的参数 -
参数<<parameter>>
- 客户类的操作返回提供者类的对象 -
实例化<<instantiate>>
B类依赖于A类的常见原因:
- A类是B类某方法中的局部变量或参数的类型
- A类向B类发送消息,从而影响B类发生变化
总而言之就是说:依赖关系是在方法中,如果不调用方法则没有关系,所有是依赖关系
类图表示
依赖者-->被依赖者
(我依赖箭头指向的他)
代码表示
public class Train{
public void move(){}
}
public class Person{
public void move(Train train){
train.move();
}
}
实现(Realization)关系
接口(interface)
接口中仅仅定义操作的规约(即操作的 特征标记),而不给出操作的实现。
-抽象方法:只有规约没有实现的操作
实现关系用来表示规格说明与实现之间的关系。
一个类可以实现多个接口,一个接口也可以被多个类实现。
使用地方:
在类图中,实现关系主要用于接口与实现该接口的类之间。
实现关系的两种表示法:
-
当接口以带构造型的类符号表示时,用虚线三角箭头表示。
-
当接口元素以小圆圈方式表示时,用实线表示。