各种关系

UML中的各种关系一览表
名称 英文名称 符号 描述 实现方法 耦合强度 举例 关键词 备注
依赖 dependency 1.当类与类之间有使用关系
时就属于依赖关系;2.依赖
不具有“拥有关系”
,而是
一种“相识关系”;3.一个
类的实现需要另一个类的协助
如果类A访问类B的属性或者方法,
或者类A负责实例化类B
,具体地,
被依赖者B是依赖者A的:1.成员
函数返回值、2.形参、3.局部
变量、4.静态方法调用​
★​ 学生使用电脑
驾驶员使用车​
使用关系​  
关联 association 一种常识上的拥有关系,但
双方又在逻辑上各自独立​
​关联者的某数据成员是指向被关
联者的指针或引用
★★​ 老师和学生是
双向关联​
拥有关系
has-a​
细分为:单向关联、
双向关联、
自身关联、多维关联​
聚合 aggregation 整体与部分的关系,且部分
可脱离整体而单独存在
同“关联”​ ★★★​ 汽车和轮胎​ 整体与部分
单独存在
contains-a​
 
组合 composition 整体与部分的关系,但部分
不能离开整体而单独存在
“整体类”的某数据成员存储
了“部分类”的实例
★★★★​ 人和头颅​ 整体与部分
不能单独存在​
 
泛化 generalization 类与类之间的继承关系,一般
与特殊
的关系,is a
类继承​ ★★★★★​ 动物和猫​ 一般与特殊
is-a​
 
实现 implementation 类与接口之间的实现关系​ 接口实现​ ★★★★★​ 鸡和鸭都实现
下蛋接口​
   

联系与区别

依赖与关联

  • 实现不同:依赖者不会将被依赖者作为自己的数据成员,但关联会。​
  • 侧重点不同:​依赖强调使用,关联强调拥有
  • 关系产生/结束时机不同:依赖关系是仅当使用关系发生(如类A的成员函数以类B的实例为参数)时而产生,伴随着使用结束而结束。关联关系当A中指向B的指针/引用被赋值时产生,当A的实例销毁时关系结束。​

关联与聚合

  • 聚合关系是关联关系的一种,是强的关联关系。
  • 逻辑关系/层次不同:关联关系所涉及的两个类处在同一个层次上,而聚合关系中,两个类处于不同的层次上,一个代表整体,一个代表部分。
  • 指向被关联/聚合者的指针/引用的初始化/赋值形式不同(这一点并非绝对):对于关联,通过A的成员函数( void A::setB(B *pB) )来为A中指向B的指针/引用赋值;对于聚合,通过带参的构造函数( A::A(B *pb) )来初始化A中指向B的指针/引用。​
  • 联和聚合在语法上无法区分,必须考察具体的逻辑关系。

聚合与组合

  • 整体与部分的生命周期不同:对于聚合,整体与部分的生命周期相互独立;对于组合,整体与部分有相同的生命周期,其中代表整体的对象负责代表部分的对象的生命周期。​
  • 构造函数不同:聚合类的构造函数中包含另一个类的实例作为参数,组合类的构造函数包含另一个类的实例化
  • 信息的封装性不同:聚合关系中,客户端可以同时了解“整体类”与“部分类”;组合关系中,客户端只认识“整体类”,“部分类”被严密封装在“整体类中”,对客户端不可见。

举例说明

下图是设计模式中命令模式(Command Pattern)的UML类图和C++实现,其中代码“改编”自这个开源项目。不熟悉命令模式的读者请自行学习。​

 1 #include <iostream>
2
3 class Receiver
4 {
5 public:
6 void Action()
7 {
8 std::cout << "Receiver: execute action" << std::endl;
9 }
10 // ...
11 };
12
13 class Command
14 {
15 public:
16 virtual ~Command() {}
17 virtual void Execute() = 0;
18
19 protected:
20 Command() {}
21 };
22
23 class ConcreteCommand : public Command
24 {
25 public:
26 ConcreteCommand(Receiver *r) : receiver(r) {}
27
28 ~ConcreteCommand()
29 {
30 if (receiver)
31 {
32 delete receiver;
33 }
34 }
35
36 void Execute()
37 {
38 receiver->Action();
39 }
40
41 private:
42 Receiver *receiver;
43 };
44
45 class Invoker
46 {
47 public:
48 void SetCommand(Command *c)
49 {
50 command = c;
51 }
52
53 void ExecuteCommand()
54 {
55 if (command)
56 {
57 command->Execute();
58 }
59 }
60
61 private:
62 Command *command = nullptr;
63 };
64
65 int main()
66 {
67 ConcreteCommand command(new Receiver());
68
69 Invoker invoker;
70 invoker.SetCommand(&command);
71 invoker.ExecuteCommand();
72
73 return 0;
74 }

Command Pattern

下面结合代码进行分析:

  • 依赖:这里的 main 函数相当于 Client , main 函数中仅仅创建并使用了 Receiver 、 ConcreteCommand 、 Invoker 的实例,相当于将它们的实例作为局部变量,因此 main 函数( Client )依赖了这三个类。​
  • 关联: ​Invoker 类中有指向 Command 或其子类的指针,该指针通过成员函数 void SetCommand(Command *c) 被赋值,因此 Invoker 关联了 Command 。
  • 聚合: ConcreteCommand 类中有指向 Receiver 的指针,该指针通过构造函数 ConcreteCommand(Receiver *r) 在 ConcreteCommand 实例被创建的同时被初始化,因此,ConcreteCommand聚合了Receiver。​

需要特别说明的是,受GoF的《Design Patterns: Elements of Reusable Object-Oriented Software》误导,几乎所有资料的UML类图都将 Ivoker 和 Command 画成了聚合关系,而将 ConcreteCommand 和 Receiver 画成了关联关系(正好跟上图相反),这显然是不对的。理由如下:​

  • “绑定”关系的牢固性不同:

    • Invoker 和 Command 通过 void Invoker::SetCommand(Command *c) 建立关系,并且,通过多次调用该函数,可以对 Invoker::command 这个成员变量赋不同的值,即 Invoker 实例可以“绑定”不同的 Command 实例,这种“绑定”是不稳定的,可更换的。​
    • 反观 ConcreteCommand ,它通过自身的构造函数 ConcreteCommand(Receiver *r) 与 Receiver 实例“绑定”,并且 ConcreteCommand 实例一旦构造完成,它所“绑定”的 Receiver 实例就不能换成其它 Receiver 实例了。显然, ConcreteCommand 和 Receiver 之间的“绑定”关系,要比 Invoker 和 Command 之间的“绑定”关系牢固得多。​
  • 关系层次不同:
    • 普通成员函数 void Invoker::SetCommand(Command *c) 暗示 Invoker 和 Command 之间是同一个层次上的“平等”关系​。
    • 构造函数 ConcreteCommand(Receiver *r) 暗示 ConcreteCommand 和 Receiver 之间是整体与部分的关系。​

参考

 
 
 
 
 
 
 
 
 
 
 
 
 

UML中的各种关系的更多相关文章

  1. 软件设计之UML—UML中的六大关系

    一.UML中的六大关系 在UML类图中,常见的有以下几种关系: 泛化(Generalization), 实现(Realization),关联(Association),聚合(Aggregation), ...

  2. [转] UML中的六大关系

    UML中的六大关系 转自:https://www.cnblogs.com/hoojo/p/uml_design.html 在UML类图中,常见的有以下几种关系: 泛化(Generalization), ...

  3. UML中的依赖关系

    UML中的五种关系和设计模式中的代码实现. 又重新听了一遍UML中的关系.感觉又是收获很大. UML中的关系有依赖,关联(聚合,组合),泛化(也叫继承),实现 现在一个一个的来实现: 一:依赖 依赖关 ...

  4. UML中的六大关系(转)

    UML定义的关系主要有六种:依赖.继承.关联.实现.聚合和组合.这些类间关系的理解和使用是掌握和应用UML的关键,而也就是这几种关系,往往会让初学者迷惑.这里给出这六种主要UML关系的说明和类图描述, ...

  5. uml中定义的关系详细详解

    uml定义的关系主要有六种:依赖.类属.关联.实现.聚合和组合.下面对其定义和表示方法逐一说明. 依赖(Dependency):元素A的变化会影响元素B,但反之不成立,那么B和A的关系是依赖关系,B依 ...

  6. UML中的六大关系

    转自:http://www.cnblogs.com/shengtianlong/archive/2010/10/23/1858953.html UML定义的关系主要有六种:依赖.类属.关联.实现.聚合 ...

  7. UML中的六种关系的比较与学习

    通过不断的学习并绘制UML图,整个画图的过程中深刻体会到其核心部分还是理解事物之间的关系,总结六大关系来深入学习,主要关系有六种:继承.实现.依赖.关联.聚合.组合. 区别于联系:         1 ...

  8. UML解惑:图说UML中的六大关系--转

    UML定义的关系主要有六种:依赖.类属.关联.实现.聚合和组合.这些类间关系的理解和使用是掌握和应用UML的关键,而也就是这几种关系,往往会让初学者迷惑.这里给出这六种主要UML关系的说明和类图描述, ...

  9. UML解惑:图说UML中的六大关系

    UML定义的关系主要有六种:依赖.类属.关联.实现.聚合和组合.这些类间关系的理解和使用是掌握和应用UML的关键,而也就是这几种关系,往往会让初学者迷惑.这里给出这六种主要UML关系的说明和类图描述, ...

  10. UML中的六种关系

    设计模式是一种对于面向对象语言(C#,C++,Java)的高级应用.其思维体现出的是真正的代码设计.每一种模式都堪称巧妙!但基于各种设计模式,这里少不了基本的类图设计,本文简要列出6种关系,及相关的例 ...

随机推荐

  1. 一站式解决方案 :OFD电子证照生成

    前言 证照的电子化是一个趋势:可以预计,未来几年内,绝大部分证照都会电子化.电子证照的种类越来越多,应用场景也复杂多样:这就给电子证照规范的制定.电子证照的生成提出了更高的要求.电子证照采用的格式有两 ...

  2. 关于win1124h2不兼容HCL

    Windows 11 24H2与HCL不兼容的问题较为复杂,以下是几种常见的解决办法: 回退系统版本 如果是在更新到Windows 11 24H2的10天内发现HCL不兼容,可以使用系统自带的回退功能 ...

  3. winform 引用AForge调用摄像头拍照

    Nuget安装这个2个: AForge.Controls; AForge.Video.DirectShow; code: namespace WindowsFormsApp1 { partial cl ...

  4. Spring Security 基于JWT的单点登陆(SSO)开发及原理解析

    JDK1.8Spring boot 2.xSpring Security 5.x 单点登录(Single Sign On),简称为SSO,是目前比较流行的企业业务整合的解决方案之一. SSO的定义是在 ...

  5. CyclicBarrier底层实现和原理

    1.CyclicBarrier 字面意思是可循环(Cyclic)使用的屏障(Barrier).它要做的事情是让一组线程到达一个屏障(同步点)时被阻塞,直到最后一个线程到达屏障时候,屏障才会开门.所有被 ...

  6. 计算困难假设(Computational hardness assumption)

    以下内容翻译自:维基 介绍 在计算复杂性理论中,计算困难假设是一个特定问题无法得到有效解决的假设(有效通常指"在多项式时间内").目前还不知道如何证明其困难性.同时,我们可以将一个 ...

  7. linux:搭建 WordPress 个人站点

    参考:链接 介绍 WordPress 是一款使用 PHP 语言开发的博客平台,您可使用通过 WordPress 搭建属于个人的博客平台.本文以 CentOS 6.5 操作系统为例,手动搭建 WordP ...

  8. linux下自建NAS教程

    NAS,英文全名Network Attached Storage,翻译过来是:网络附接存储. 引用维基百科定义 网络附接存储(英语:Network Attached Storage,缩写:NAS)[1 ...

  9. webstorm前端vue项目安装依赖包总结

    npm install提示错误信息,与node.js版本有关.以下是用到的一些命令行参数: 1.清除npm的缓存:npm cache clean --force 2.设置npm下载镜像:npm con ...

  10. Prometheus修改默认数据存储时间

    Prometheus修改默认数据存储时间 Prometheus 的数据存储时间是通过命令行参数 --storage.tsdb.retention.time 来设置的.这个参数指定了 Prometheu ...