一、概述
我们可以使用模型和图,以视图方式表示要构建的系统。在 UML 模型中,关系是向模型添加语义信息的两个或更多个 UML 模型元素之间的连接。
在产品中,可以使用多种 UML 关系来定义模型元素之间的结构。这些关系的示例包括:关联、依赖关系、泛化关系、实现和转换。
二、UML常用图形说明
- 用例图
可通过用例图对完整系统或系统的各部分的必需行为进行建模。 - 活动图
在 UML 建模中,可以使用活动图对必须在系统或应用程序中执行的一系列操作进行建模,或者用来描述业务流程工作流程中发生的事件。 - 类图
类图对一个包或整个系统的静态结构进行建模。 - 对象图
在 UML 中,对象图用于对系统中类元的实例以及这些实例之间在某一时刻存在的关系建模。可以使用对象图来探查行为方案,说明对象的样本配置,或者对类图进行测试以验证规则和定义。 - 时序图
在 UML 模型中,交互是用来表示一个或多个参与者之间的通信的行为。时序图是一种 UML 交互图,它对在参与者之间传递的消息(例如,对象和角色)以及控制和条件结构(例如,组合片段)进行建模。可以创建新的时序图,使用源元素来填充现有时序图以及对时序图添加生命线、消息和组合片段。 - 通信图
在 UML 模型中,交互是用来表示一个或多个参与者之间的通信的行为。通信图是一种 UML 交互图,用来说明参与交互的对象之间的消息流。可以在通信图中添加和修改生命线、消息路径和消息。 - 组合结构图
在 UML 模型中,组合结构图使用部件、端口和连接器来显示类元和协作的内部结构。可以使用组合结构图来以可视方式说明包含类元的组合部件以及定义各个部件之间的行为和通信。 - 状态机图
可使用状态机图来说明类、协作、组件、节点、操作、用例或完整系统的行为。 - 组件图
可以使用组件图来对系统的软件体系结构建模。组件图提供了系统中的物理软件组件及其接口和依赖关系的视图。 - 部署图
可以使用部署图对系统的物理布局或拓扑进行建模。部署图描述运行时处理节点的配置和部署在这些节点上的工件。
二、图形关系种类及描述
关系 | 描述 |
---|---|
抽象 | 抽象关系就是在不同抽象级别或者从不同视点来表示同一概念的模型元素之间的依赖关系。可以在多个图(包括用例图、类图和组件图)中对模型添加抽象关系。 |
聚集 | 聚集关系描述一个类元是另一个类元的一部分或者从属于另一个类元。 |
关联 | 关联关系是两个模型元素之间的一种结构关系,它表示一个类元(参与者、用例、类、接口、节点或组件)的对象连接至另一个类元的对象,并且可浏览至这些对象。即使在双向关系中,关联也将连接两个类元,一个是主类元(供应者),另一个是辅助类元(客户)。 |
绑定 | 绑定关系是一种为模板参数指定值并从模板生成新的模型元素的依赖关系。 |
通信路径 | 通信路径是部署图中的节点之间的一种关联类型,它说明节点之间如何交换消息和信号。 |
组合 | 组合关系是一种表示整体与部分的关系的聚集。组合关系指定部分类元的生存期取决于完整类元的生存期。 |
控制流 | 控制流是一种活动边,它对一个活动节点与另一个活动节点之间的控制活动进行建模。 |
依赖关系 | 依赖关系表示更改一个模型元素(供应者或独立模型元素)会导致更改另一个模型元素(客户或从属模型元素)。供应者模型元素是独立的,这是因为更改客户并不会影响该模型元素。客户模型元素依赖于供应者模型元素,这是因为更改供应者将影响客户。 |
部署 | 部署关系显示单个节点的实例使用的特定组件。在 UML 模型中,部署关系通常出现在部署图中。 |
有向关联 | 有向关联关系是一种只能朝一个方向浏览的关联。在这种关联中,控制流从一个类元流向另一个类元,例如,从参与者流向用例。只有一个关联关系端指定了可导航性。 |
扩展 | 用例之间的扩展关系表示一个用例(已扩展的用例)可以扩展另一个用例(基本用例)。扩展关系可以选择使用已扩展的用例。 |
泛化关系 | 泛化关系表示私有模型元素(子代)基于通用模型元素(父代)。尽管父模型元素可以具有一个或多个子模型元素,且任何子模型元素可以具有一个或多个父模型元素,但是单个父模型元素通常具有多个子模型元素。在 UML 2.0 中,多个类可以组成另一个类的泛化关系集合。泛化关系出现在类图、组件图和用例图中。 |
接口实现 | 接口实现关系是类元与所提供接口之间的私有类型的实现关系。接口实现关系指定在实现类元时必须遵守提供的接口指定的合同。 |
包含 | 用例之间的包含关系指定包含用例(或基本用例)需要另一个用例(被包含的用例)的行为。在包含关系中,一个用例必须使用被包含的用例。 |
表现 | 表现关系表示在一个工件中表现了的模型元素,例如,组件或类。该工件表现或包含一个或多个物理软件组件的功能部件的特定实现。 |
注解连接 | 注解连接关系将一个注解或文本框连接至一个连接器或形状。注解连接表示注解或文本框中包含与所连接的连接器或形状相关的信息。 |
对象流 | 对象流是一种活动边,它对一个活动节点与另一个活动节点之间的对象流和数据流进行建模。 |
实现 | 如果一个模型元素必须实现另一个模型元素指定的行为,那么这两个模型元素之间就存在实现关系。指定行为的模型元素就是供应者,而实现行为的模型元素就是客户。在 UML 2.0 中,此关系通常用来指定将实现一个组件的行为的那些模型元素。 |
使用 | 使用关系是一种依赖关系。如果一个模型元素需要存在另一个模型元素(或一组模型元素)才能完全实现或操作,那么这两个模型元素之间就存在使用关系。需要存在另一个模型元素的模型元素就是客户,而需要存在的模型元素就是供应者。尽管使用关系指示当前的需求,但是它还指示两个模型元素之间的连接并不是始终有意义或存在。 |
三、类图关系解析
1.依赖(Dependency)
依赖关系使用虚线加箭头表示,如下图所示:
学生在学习生活中经常使用电脑,于是对电脑产生了依赖。依赖关系是五种关系中耦合最小的一种关系。类A要完成某个功能引用了类B,则类A依赖类B。依赖在代码中主要体现为类A的某个成员函数的返回值、形参、局部变量或静态方法的调用,则表示类A引用了类B。以Student类和Computer类为例,用C++语言编码如下:
class Computer
{
public:
static void start(){
cout<<"电脑正在启动"<
2.关联(Association)
关联关系使用实线加箭头表示,类之间的关系比依赖要强。学生与老师是关联的,学生可以不用电脑,但是学生不能没有老师。如下图所示:
关联与依赖的对比:
相似之处:
关联暗示了依赖,二者都用来表示无法用聚合和组合表示的关系。
区别:
(1)发生依赖关系的两个类都不会增加属性。其中的一个类作为另一个类的方法的参数或者返回值,或者是某个方法的变量而已。
发生关联关系的两个类,类A成为类B的属性,而属性是一种更为紧密的耦合,更为长久的持有关系。 在代码中的表现如下:
class Teacher;
class Student{
public:
Teacher teacher; //成员变量
void study();
}
(2)从关系的生命周期来看,依赖关系是仅当类的方法被调用时而产生,伴随着方法的结束而结束。关联关系当类实例化的时候产生,当类对象销毁的时候关系结束。相比依赖,关联关系的生存期更长。
关联关系有单向关联、双向关联、自身关联、多维关联等等。其中后三个可以不加箭头。
单向关联:
双向关联:
**自身关联:
**多维关联:
3.聚合(Aggregation)
聚合关系使用实线加空心菱形表示。聚合用来表示集体与个体之间的关联关系。例如班级与学生之间存在聚合关系,类图表示如下:
聚合关系在代码上与关联关系表现一致,类Student将成为类Classes的成员变量。代码如下:
class Student;
class Classes{
public:
Student* student;
Classes(Student* stu):student(stu){}
};
4.组合(复合,Composition)
复合关系使用实线加实心菱形表示。组合又叫复合,用来表示个体与组成部分之间的关联关系。例如学生与心脏之间存在复合关系,类图表示如下:
组合关系在代码上与关联关系表现一致,类Heart将成为类Student的成员变量。代码如下:
class Heart;
class Student
{
public:
Heart* heart;
Student()
{
heart=new Heart;
}
~Student()
{
delete heart;
}
};
聚合与组合的对比:
(1)聚合关系没有组合紧密。
学生不会因为班级的解散而无法存在,聚合关系的类具有不同的生命周期;而学生如果没有心脏将无法存活,组合关系的类具有相同的生命周期。
这个从构造函数可以看出。聚合类的构造函数中包含另一个类的实例作为参数,因为构造函数中传递另一个类的实例,因此学生可以脱离班级体独立存在。组合类的构造函数包含另一个类的实例化。因为在构造函数中进行实例化,因此两者紧密耦合在一起,同生同灭,学生不能脱离心脏而存在。
(2)信息的封装性不同。
在聚合关系中,客户端可以同时了解Classes类和Student类,因为他们是独立的。
在组合关系中,客户端只认识Student类,根本不知道Heart类的存在,因为心脏类被严密地封装在学生类中。
理解聚合与复合的区别,主要在于聚合的成员可独立,复合的成员必须依赖于整体才有意义。
5.泛化(Generalization)
泛化是学术名称,通俗来讲,泛化指的是类与类之间的继承关系和类与接口之间的实现关系。
继承关系使用直线加空心三角形表示。类图结构如下:
类接口的实现关系使用虚线加空心三角形表示。类图结构如下:
6.小结
依赖、关联、聚合、组合与泛化代表类与类之间的耦合度依次递增。依赖关系实际上是一种比较弱的关联,聚合是一种比较强的关联,组合是一种更强的关联,泛化则是一种最强的关联,所以笼统的来区分的话,实际上这五种关系都是关联关系。
依赖关系比较好区分,它是耦合度最弱的一种,在编码中表现为类成员函数的局部变量、形参、返回值或对静态方法的调用。关联、聚合与组合在编码形式上都以类成员变量的形式来表示,所以只给出一段代码我们很难判断出是关联、聚合还是组合关系,我们需要从上下文语境中来判别。关联表示类之间存在联系,不存在集体与个体、个体与组成部分之间的关系。聚合表示类之间存在集体与个体的关系。组合表示个体与组成部分之间的关系。
依赖、关联、聚合与组合是逻辑上的关联,泛化是物理上的关联。物理上的关联指的是类体的耦合,所以类间耦合性最强。