设计模式(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 图绘制以及类之间关系的个人理解,如果有误欢迎指出~
相关文章:

设计模式(1) - UML类图
1、前言 最近在阅读 Android 源码,时常碰到代码中有一些巧妙的写法,简单的如 MediaPlayerService 中的 IFactory,我知道它是工厂模式,但是却不十分清楚它为什么这么用;复杂点的像 NuPlayer 中的 DeferredActions 机制…...

3D异常检测论文笔记 | Shape-Guided Dual-Memory Learning for 3D Anomaly Detection
文章目录 摘要一、介绍三、方法3.1. 形状引导专家学习3.2. Shape-Guided推理 摘要 我们提出了一个形状引导的专家学习框架来解决无监督的三维异常检测问题。我们的方法是建立在两个专门的专家模型的有效性和他们的协同从颜色和形状模态定位异常区域。第一个专家利用几何信息通…...

如何将枯燥的大数据进行可视化处理?
在数字时代,大数据已经成为商业、科学、政府和日常生活中不可或缺的一部分。然而,大数据本身往往是枯燥的、难以理解的数字和文字,如果没有有效的方式将其可视化,就会错失其中的宝贵信息。以下是一些方法,可以将枯燥的…...

linux bash中 test命令详解
test命令用于检查某个条件是否成立。它可以进行数值、字符和文件三方面的测试。 1、数值测试 -eq 等于-ne 不等于-gt 大于-ge 大于或等于-lt 小于-le 小于或等于 例如,我们可以测试两个变量是否相等: num1100 num2200 if test $num1 -eq $num2 thene…...

获取当前时间并转换为想要的格式
转换为YYYY-MM-DD格式 function getCurrentDate() {var today new Date();var year today.getFullYear();var month today.getMonth() 1; // 月份从0开始,需要加1var day today.getDate();return year - (month < 10 ? (0 month) : month) - (day &…...

如何实现自动化测试?
一、首先我们要清楚自动化测试的分类 以实现方式可分为UI自动化和接口自动化。UI自动化可用selenium等工具实现,接口自动化可用使用RobotFramework和Jmeter等工具实现,Jmeter也可做性能自动化,压力测试。 二、平时自动化测试怎么做 1. UI和…...

c++中的对齐问题
c中的对齐问题 需要对齐的原因 尽管内存是以字节为单位,但是大部分处理器并不是按字节块来存取内存的.它一般会以双字节,四字节,8字节,16字节甚至32字节为单位来存取内存,我们将上述这些存取单位称为内存存取粒度. 现在考虑4字节存取粒度的处理器取in…...

力扣(LeetCode)算法_C++—— 存在重复元素
给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。 示例 1: 输入:nums [1,2,3,1] 输出:true 示例 2: 输入:nums …...

OpenCV实现Photoshop曲线调整
《QT 插件化图像算法研究平台》有仿Photoshop曲线调整图像的功能,包括RGB曲线调整和HSV曲线调整。 Photoshop曲线调整原理:RGB、HSV各通道曲线,可以理解为一个值映射(值转换)函数。X轴是输入,Y轴是输出。x0…...

【探索Linux】—— 强大的命令行工具 P.8(进程优先级、环境变量)
阅读导航 前言一、进程优先级1. 优先级概念2. Linux查看系统进程3. PRI(Priority)和NI(Nice) 二、环境变量1. 概念2. 查看环境变量方法3. 环境变量的组织方式4.通过代码获取环境变量5. 环境变量的特点 总结温馨提示 前言 前面我们…...

蓝牙协议栈BLE
前言 这阵子用到蓝牙比较多,想写一个专栏专门讲解蓝牙协议及其应用,本篇是第一篇文章,讲解低功耗蓝牙和蓝牙协议栈。 参考网上各大神文章,及瑞萨的文章,参考GPT,并且加入了一些本人的理解。 图片部分源自…...

企业架构LNMP学习笔记17
反向代理: 反向代理服务器和真实访问的服务器是在一起的,有关联的。 根据实际业务需求,分发代理页面到不同的解释器。常见于代理后端服务器。 安装apache服务器: yum install -y httpd 修改配置文件: vim /et/http…...

php 获取每月开始结束时间,指定月份的开始结束时间戳
php 获取指定月份的开始结束时间戳。 /** * * 获取指定年月的开始和结束时间戳 * param int $year 年份 * param int $month 月份 * return array(开始时间,结束时间) */ function getMonthBeginAndEnd($year 0, $month 0) {$year $year ? $year : date(Y);$month $month…...

Docker技术入门| Part03:Dockerfile详解(Dockerfile概念、Dockerfile 指令、使用Dockerfile构建镜像)
文章目录 1. Dockerfile概念2. Dockerfile 指令FROM 指定基础镜像RUN执行命令CMD 容器启动命令COPY 复制文件ADD 更高级的复制文件ENV 设置环境变量ARG 构建参数VOLUME 定义匿名卷EXPOSE 暴露端口WORKDIR 指定工作目录USER 指定当前用户LABEL 为镜像添加元数据SHELL 指令 3. 使…...

分享一个有意思的线程相关的程序运行题
翻开之前的代码,发现了一个有意思的代码,猜以下代码的运行结果: package thread;/*** author heyunlin* version 1.0*/ public class ThreadMethodExample {public static void main(String[] args) {Thread thread new Thread(new Runnabl…...

集合的进阶学习
集合体系结构 Collection 单列集合 包含List Set List 包含ArrayList LinkedList Set包含HashSet TreeSet HashSet包含LinkedHashSet List系列集合:添加的元素是有序的、可重复、有索引 Set系列集合:添加的元素是无序的、不重复、无索引 Collectio…...

Java真过饱和了吗?现在学Java迟了?
Java行业内幕揭秘 我是某有名机构的线下课Java老师,负责Java热门框架教学,如Spring、Spring MVC、Spring Boot。但最近被解雇了,让我来吐槽一下。Java现在的学习人数真的太多太多了。 Java的学习饱和度 Java学习的人太多,给你一…...

glibc2.35-通过tls_dtor_list劫持exit执行流程
前言 glibc2.35删除了malloc_hook、free_hook以及realloc_hook,通过劫持这三个hook函数执行system已经不可行了。 传统堆漏洞利用是利用任意地址写改上上述几个hook从而执行system,在移除之后则需要找到同样只需要修改某个地址值并且能够造成程序流劫持…...

linux-OpenSSL升级
1.安装编译所需的安装包 yum install -y gcc make perl zlib-devel 2.从 OpenSSL 官网下载(https://www.openssl.org/source/openssl-1.1.1v.tar.gz) 注:如果原先版本为1.x.x,升级时还是需要选择1.x.x 3. 编译安装 # 解压tar -xvf openssl-1.1.1v.tar…...

Nginx全家桶配置详解
源码包安装NGINX A,搭建Web Server,任意HTML页面,其8080端口提供Web访问服务,截图成功访问http(s)://[Server1]:8080并且回显Web页面。保留Server1,但是不允许直接访问Server 1,再部署1套NGINX …...

CMake生成Visual Studio工程
CMake – 生成Visual Studio工程 C/C项目经常使用CMake构建工具。CMake 项目文件(例如 CMakeLists.txt)可以直接由 Visual Studio 使用。本文要说明的是如何将CMake项目转换到Visual Studio解决方案(.sln)或项目(.vcxproj) 开发环境 为了生成Visual S…...

数学建模--K-means聚类的Python实现
目录 1.算法流程简介 2.1.K-mean算法核心代码 2.2.K-mean算法效果展示 3.1.肘部法算法核心代码 3.2.肘部法算法效果展示 1.算法流程简介 #k-means聚类方法 """ k-means聚类算法流程: 1.K-mean均值聚类的方法就是先随机选择k个对象作为初始聚类中心. 2.这…...

防坠安全带上亚马逊美国站要求的合规标准是什么?
防坠安全带 防坠安全带是一种防护装备,适合工人在高空作业时或在可能发生跌落的无防护边缘行走时穿着。防坠安全带设计用于包裹身体躯干,并将坠落力至少分布到大腿上部、骨盆、胸部和肩部。防坠安全带是固定物体与非固定物体之间的连接物,通…...

PDF转Word的方法分享与注意事项。
PDF和Word是两种常用的文档格式,它们各有优点,适用于不同的场景。然而,有时候我们需要将PDF转换为Word,以便更好地进行编辑和排版。本文将介绍几种常用的PDF转Word的方法,并分享一些注意事项。 一、PDF转Word的方法 使…...

gitlab配置webhook,commit message的时候校验提交的信息
在 GitLab 中配置 Webhook 来调用 Java 接口以校验 commit 信息,是很多公司的一些要求,因为提交信息的规范化是必要的 在 GitLab 项目中进入设置页面。 在左侧导航栏中选择 “Webhooks”(Web钩子)。 在 Webhooks 页面中点击 “…...

借助CIFAR10模型结构理解卷积神经网络及Sequential的使用
CIFAR10模型搭建 CIFAR10模型结构 0. input : 332x32,3通道32x32的图片 --> 特征图(Feature maps) : 3232x32即经过32个35x5的卷积层,输出尺寸没有变化(有x个特征图即有x个卷积核。卷积核的通道数与输入的通道数相等,即35x5&am…...

Java # Java基础八股
1、JVM、JRE、JDK之间的关系 个人理解:JVM可以帮助屏蔽底层的操作系统,使程序一次编译到处都可以运行,JVM可以运行class文件。JRE是java文件运行的环境,但不能新建程序,JRE包含JVM。JDK功能最齐全,包含了编…...

【Spring Boot】SpringBoot 2.6.6 集成 SpringDoc 1.6.9 生成swagger接口文档
文章目录 前言一、SpringDoc是什么?二、使用步骤1.引入库2.配置类3.访问测试 总结其他配置立个Flag 前言 之前常用的SpringFox在2020年停止更新了,新项目集成SpringFox出来一堆问题,所以打算使用更活跃的SpringDoc,这里简单介绍一…...

【算法】快速排序 详解
快速排序 详解 快速排序1. 挖坑法2. 左右指针法 (Hoare 法)3. 前后指针法4. 快排非递归 代码优化 排序: 排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 稳定性&…...

架构师spring boot 面试题
spring boot 微服务有哪些特点? Spring Boot 微服务具有以下特点: 独立性:每个微服务都是独立的部署单元,有自己的代码库和数据库。这使得微服务可以独立开发、测试、部署和扩展。 分布式:微服务架构将一个大型应用程…...