各种关系

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. 内华达大地测量实验室GNSS数据tenv3格式下载

    GNSS时序形变位移数据下载 引言 下载方式 注意事项 引言 目的:教大家如何下载GNSS时序形变位移数据,本人主要是利用GNSS位移结果进行InSAR相关成果的精度验证工作.若大家需要在自己的研究领 ...

  2. Redis 源码简洁剖析 08 - epoll

    select, poll, epoll 源码分析 参考链接 Redis 源码简洁剖析系列 select, poll, epoll 关于 select, poll, epoll,​网络 IO 演变发展过 ...

  3. 【狂神说Java】Java零基础学习笔记-异常

    [狂神说Java]Java零基础学习笔记-异常 异常01:Error和Exception 什么是异常 实际工作中,遇到的情况不可能是非常完美的.比如:你写的某个模块,用户输入不一定符合你的要求.你的程 ...

  4. Swagger介绍和应用

    1.什么是swaggerSwagger是一个规范和完整的框架,用于生成.描述.调用和可视化RESTful风格的Web服务.简单来说,Swagger是一个功能强大的接口管理工具,并且提供了多种编程语言的 ...

  5. 一个9年archlinux重度使用者自述

    系统没有高低贵贱,主要还是使用的人,哪个跟你更契合.对我而言, archlinux就是最契合的那个.本文主要是对archlinux使用做一个粗浅的介绍,如果能勾起你一丝兴趣,那就更好了. 第一部分:初 ...

  6. Q:浏览器打开控制台报错:net::ERR_CONTENT_LENGTH_MISMATCH 206

    一.问题描述 F12查看浏览器的控制台,提示net::ERR_CONTENT_LENGTH_MISMATCH 206 (Partial Content) ,如下图, HTTP状态码206表示" ...

  7. KVM快照管理

    [root@kvm1 ~]# virsh virsh # list --all Id Name State ---------------------------------------------- ...

  8. WPF DockLayoutManager布局后的布局重置

    初始化布局 Logging.InfoBiz("初始化布局信息"); dockLayoutManager = new DockLayoutManager(); RestoreLayo ...

  9. VS2019 找不到资产文件 “xxxx\obj\project.assets.json”运行NuGet包还原以生成此文件

    参考地址:https://blog.csdn.net/weixin_42835409/article/details/107033059 下载 log4net 源码打开,编译报错: 严重性 代码 说明 ...

  10. 使用 DeepSeek R1 和 Ollama 开发 RAG 系统

    1.概述 掌握如何借助 DeepSeek R1 与 Ollama 搭建检索增强生成(RAG)系统.本文将通过代码示例,为你提供详尽的分步指南.设置说明,分享打造智能 AI 应用的最佳实践. 2.内容 ...