设计模式(1) - UML类图

1、前言

最近在阅读 Android 源码,时常碰到代码中有一些巧妙的写法,简单的如 MediaPlayerService 中的 IFactory,我知道它是工厂模式,但是却不十分清楚它为什么这么用;复杂点的像 NuPlayer 中的 DeferredActions 机制,我只能慢慢揣摩它是如何工作的,最终也能琢磨出个大差不差;有些特点不太鲜明的如 NuPlayer Source 中的 wrapper,我就不是很理解它为什么要这么写了。

深入 Android 源码细节实现时,常常因为不理解其中这些设计的思路,从而看的云里雾里,觉得作者写的晦涩难懂;有的时候猛然揣摩出作者的用意,又觉得豁然开朗,拍手叫好。一前一后两种不同的心境,我觉得差别在于是否了解设计模式。

了解设计模式可以让我在阅读优秀工程时能够更好更快地了解代码架构、作者意图,更轻松地学习内部实现,最后能够更加灵活地运用。

2、UML 类图

庞大的工程往往具有相当多且复杂地类,阅读这些类时我们常常会用 UML 类图来展示复杂的类关系。以下是一个简单的 UML 类图示例:
请添加图片描述

  • 车是一个抽象类;
  • 汽车继承于车,它和车的关系为实现关系,使用带空心箭头的虚线表示;
  • 轿车和汽车之间也是继承关系,它们之间的关系为泛化关系,使用带空心箭头的实线表示;
  • 发动机与汽车之间是组合关系,使用带实心箭头的实线表示;
  • 学生与班级之间是聚合关系,使用带空心箭头的实线表示;
  • 学生和校园卡之间为关联关系,使用带箭头的实线表示;
  • 学生上学要用自行车,与自行车是一种依赖关系,使用带箭头的虚线表示;

3、类之间的关系

3.1、实现关系

实现关系指的是将抽象概念变成现实实现。拿上面的示例来说,我们只知道车可以移动,但是不知道车长什么样子,要如何移动,所以它只是一个概念。汽车包含有发动机、变速箱等组件,踩油门就可以移动;自行车两个轮胎一个把手,用脚踩就可以移动。汽车和自行车将虚无的(抽象)概念变成现实,所以用带虚线的箭头表示实现关系。

在代码中,实现关系表现为继承抽象类。

3.2、泛化关系

泛化关系指的是具体事物的不同形态。同样拿车为例子,我们已经知道车由变速箱、发动机等组成,但是它们仍可以组成不同的形态,如轿车和SUV,它们都属于汽车,但是又有各自的特点。

在代码中,泛化关系表现为继承非抽象类;

以 MediaPlayerInterface.h 为例,MediaPlayerInterface 继承于 MediaPlayerBase,并且实现了 hardwareOutput,这个关系是属于实现还是泛化关系呢?

个人以为是泛化关系,将 MediaPlayerBase 泛化为使用 software mixer 和 hardware output 两种 player。泛化关系常常会修改基类方法或者是新增对外接口,可能会影响多态的使用(需要做强转才能调用泛化类的新接口)。

例如 MediaPlayerBase 在实际使用中需要做强制转换才能实现 setAudioSink 的调用。

	sp<MediaPlayerBase> p = createPlayer(playerType);if (!p->hardwareOutput()) {mAudioOutput = new AudioOutput(mAudioSessionId, mAttributionSource,mAudioAttributes, mAudioDeviceUpdatedListener);static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);}

泛化关系见的比较少,下次碰见再补充到这里

3.3、聚合关系

聚合关系指的是整体和个体,整体由个体组成,但是整体不存在并不会影响个体。例如 buffer list 和 buffer 的关系,buffer 可以组成 buffer list,buffer list 不存在并不会影响 buffer。

3.4、组合关系

组合关系表示的是部分和整体的关系,它和聚合关系由比较大的区别,组合关系的整体不存在了,部分也就不存在了,反之也一样。

可能有的人会不理解什么叫“整体不存在了部分也就不存在了;部分不存在了整体也不存在了”,这里以 ACodec.h 为例,ACodec 中有一个 mBufferChannel 成员,ACodec 销毁了,那么 mBufferChannel 也就随之销毁了,这里体现的就是组合关系;如果 mBufferChannel 销毁了,那么 ACodec 自然也就无法工作了。

之前看汽车和发动机的例子会有一些疑惑,明明发送机可以独立存在,为什么它和汽车还是组合关系呢?应该是这么理解,如果没有汽车,也就没有发动机存在的必要了,所以说是没有整体也就没有部分。

组合关系比聚合关系更加强烈,所以用的是黑色箭头。

在代码中,聚合关系 和 组合关系通常以成员变量体现出来,具体属于哪一种还需要自己揣摩。

3.5、关联关系

个人理解关联关系表示的是拥有,比如说学生拥有自行车,那么学生就和自行车有了关联。

在代码中,关联关系同样是以成员变量体现出来,但是属于拥有的关系,和上面的组合与聚合不一样,并不需要自行车才能够组成一个人。

3.6、依赖关系

依赖关系表示的是调用的关系,它是一种临时性关系,在代码中体现为参数传入。再举个例子,学生每天骑共享单车上学,车不属于学生,但是学生每天需要使用自行车,这就属于依赖关系。如果学生有了车,那么可能就要归类于关联关系了。

好了,以上就是我对 UML 图绘制以及类之间关系的个人理解,如果有误欢迎指出~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/100382.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络编程day6作业

完成网络聊天室编写 ser #define ERR_MSG(msg) do{\fprintf(stderr,"__%d__",__LINE__);\perror(msg);\ }while(0) #define IP "127.0.0.1" #define PORT 6666 //创建链表 Linklistptr list_create(); Linklistptr node_buy(datatype e); int list_inser…

matlab 计算矩阵的条件数

目录 一、概述1、算法概述2、主要函数3、参考文献二、代码实现三、结果展示四、参考链接本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、概述 1、算法概述 条件数法是目前应用最为广泛的一种病态诊断方法。一个方阵…

npm修改为国内镜像

npm config get registry 查看下载地址&#xff0c;默认是https://registry.npmjs.org/ 这是国外的地址&#xff0c;npm下载很慢 npm config set registry https://registry.npmmirror.com/ 使用此指令&#xff0c;修改为淘宝镜像&#xff0c;输入指令后检查是否修改成功 …

[当人工智能遇上安全] 8.基于API序列和机器学习的恶意家族分类实例详解

您或许知道&#xff0c;作者后续分享网络安全的文章会越来越少。但如果您想学习人工智能和安全结合的应用&#xff0c;您就有福利了&#xff0c;作者将重新打造一个《当人工智能遇上安全》系列博客&#xff0c;详细介绍人工智能与安全相关的论文、实践&#xff0c;并分享各种案…

ETCD详解

一、etcd概念 ETCD 是一个高可用的分布式键值key-value数据库&#xff0c;可用于服务发现。 ETCD 采用raft 一致性算法&#xff0c;基于 Go语言实现。 etcd作为一个高可用键值存储系统&#xff0c;天生就是为集群化而设计的。由于Raft算法在做决策时需要多数节点的投票&…

华为数据管理——《华为数据之道》

数据分析与开发 元数据是描述数据的数据&#xff0c;用于打破业务和IT之间的语言障碍&#xff0c;帮助业务更好地理解数据。 元数据是数据中台的重要的基础设施&#xff0c;元数据治理贯彻数据产生、加工、消费的全过程&#xff0c;沉淀了数据资产&#xff0c;搭建了技术和业务…

【Arduino24】8*8点阵实验

硬件准备 8*8点阵&#xff1a;1个 旋钮电位器&#xff1a;1个 面包板&#xff1a;1块 杜邦线&#xff1a;若干 硬件连线 软件程序 //定义引脚 #define xKnob_pin A0 //x轴旋钮的引脚 #define yKnob_pin A1 //y轴旋钮的引脚 const int row_pin[8] { 6, 11, 10, 3, 17, 4…

pandas(四十三)Pandas实现复杂Excel的转置合并

一、Pandas实现复杂Excel的转置合并 读取并筛选第一张表 df1 pd.read_excel("第一个表.xlsx") df1# 删除无用列 df1 df1[[股票代码, 高数, 实际2]].copy() df1df1.dtypes股票代码 int64 高数 float64 实际2 int64 dtype: object读取并处理第二张表…

李宏毅-21-hw3:对11种食物进行分类-CNN

一、代码慢慢阅读理解总结内化&#xff1a; 1.关于torch.nn.covd2d()的参数含义、具体用法、功能&#xff1a; &#xff08;1&#xff09;参数含义&#xff1a; 注意&#xff0c;里面的“padding”参数&#xff1a;《both》side所以是上下左右《四》边都会加一个padding数量…

sqlserver数据库链接mysql服务器访问数据

sqlserver数据库链接mysql服务器访问数据 关于SqlServer数据库怎么链接mysql数据库我一直不明白&#xff0c;今天项目碰到一个问题需要链接&#xff0c;我就研究了一下&#xff0c;然后就成功了&#xff0c;在这里记录一下。也欢迎朋友互相学习交流借鉴。 1.使用navicat打开S…

使用Maven创建父子工程

&#x1f4da;目录 创建父工程创建子模块创建子模块示例创建认证模块(auth) 结束 创建父工程 选择空项目&#xff1a; 设置&#xff1a;项目名称&#xff0c;组件名称&#xff0c;版本号等 创建完成后的工程 因为我们需要设置这个工程为父工程所以不需要src下的所有文件 在pom…

学习笔记|计数器|Keil软件中 0xFD问题|I/O口配置|STC32G单片机视频开发教程(冲哥)|第十二集:计数器的作用和意义

文章目录 1.计数器的用途2.计数器的配置官方例程开始Tips&#xff1a;编译时提示错误FILE DOES NOT EXIST&#xff1a; 3.计数器的应用本例完整代码&#xff1a;总结课后练习&#xff1a; 1.计数器的用途 直流有刷的电机,后面两个一正一负的电接上,电机就可以转 到底是转子个…