设计模式(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 …...
【原创改进代码】考虑电动汽车移动储能特性的多区域电网功率波动平抑优化调控附python代码
✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 🍎 往期回顾关注个人主页:Matlab科研工作室 👇 关注我领取海量matlab电子…...
STM32F746G-DISCO音频BSP详解:I2S+DMA+CS43L22驱动开发
1. 项目概述AUDIO_DISCO_F746NG是 STMicroelectronics 官方 STM32CubeF7 软件包中为STM32F746G-DISCO 探索套件提供的音频底层支持包(Board Support Package, BSP)核心类。该类并非独立音频处理库,而是面向硬件抽象层(HAL…...
从‘迷失’到‘秒达’:我用PyCharm的‘符号搜索’和‘调用链查看’重构了老项目
从‘迷失’到‘秒达’:我用PyCharm的‘符号搜索’和‘调用链查看’重构了老项目 接手一个缺乏文档的遗留代码库,就像被扔进一座没有地图的迷宫。上周我面对的就是这样一个Python项目——3万行代码,零文档,函数命名随意得像临时起意…...
STM32环境检测系统设计与物联网应用
1. 项目概述这个基于STM32的环境检测系统是我去年为一个工业客户开发的解决方案,经过3个月的迭代优化已经稳定运行了半年多。系统通过多种传感器实时监测环境参数,并将数据上传至OneNet云平台,实现了本地和远程的双重监控。提示:项…...
集团型企业BI试点,为什么一定要先做多域资源隔离?
艾瑞咨询《2025年中国BI市场报告》显示,超7成集团型企业的首次BI试点项目因跨业务单元权限冲突、数据口径混乱延期或终止(统计样本覆盖120家年营收超50亿的国内集团企业,统计窗口为2022-2024年试点项目全生命周期)。这个数据和大部…...
VictoriaMetrics 集群版实战指南:架构解析与最佳实践
1. VictoriaMetrics集群版架构深度解析 第一次接触VictoriaMetrics集群版时,我被它简洁的组件划分惊艳到了。与常见的时序数据库不同,它的三大核心组件vmstorage、vminsert、vmselect各司其职,这种设计让横向扩展变得异常灵活。在实际部署中&…...
爬虫自动化(DrissionPage)
目录 ?一.介绍: 下载DrissionPage,还是我们熟悉的pip: 环境准备: ?二.基本代码: 它对于的导包和类使用: 窗口的设置: 和获取的页面的滑动: 3.进一步认识DrissionPage: 浏览器可以多开…...
如何在Charmbracelet Log中实现结构化日志记录的5个技巧
如何在Charmbracelet Log中实现结构化日志记录的5个技巧 【免费下载链接】log A minimal, colorful Go logging library 🪵 项目地址: https://gitcode.com/gh_mirrors/log1/log Charmbracelet Log是一款轻量级且色彩丰富的Go日志库,支持结构化日…...
S2-Pro模型推理服务高可用部署:基于Docker与Kubernetes的架构
S2-Pro模型推理服务高可用部署:基于Docker与Kubernetes的架构 1. 为什么需要高可用部署 在实际生产环境中,AI模型推理服务的稳定性直接影响业务连续性。想象一下,当你的电商平台正在举行大促活动,AI推荐系统突然宕机,…...
SpringBoot + MyBatis-Plus项目实战:从零搭建一个JavaEE课程设计骨架(附完整源码结构解析)
SpringBoot MyBatis-Plus项目实战:从零搭建一个JavaEE课程设计骨架(附完整源码结构解析) 当你第一次打开IDE准备开始JavaEE课程设计时,面对空白的项目窗口是否感到无从下手?本文将带你从零开始,用SpringBo…...
