Java设计模式七大原则-合成聚合复用原则
🧑💻作者:猫十二懿
❤️🔥账号:CSDN 、掘金 、个人博客 、Github
🎉公众号:猫十二懿
合成-聚合复用原则
1、合成-聚合复用原则介绍
合成/聚合复用原则(Composition/Aggregation Reuse Principle,CARP)是一种面向对象设计原则,它提倡通过合成/聚合关系(组合关系)来达到代码复用的目的,而不是通过继承关系。
1.1 继承与组合对比
CARP 的基本思想是在设计类之间的关系时,优先选择合成/聚合关系,而不是继承关系。通过将对象组合在一起形成更大的对象,来达到复用的目的。
继承关系在某些情况下可能导致代码的耦合性增加,使得系统的灵活性和可维护性下降。
而合成 / 聚合关系则可以更加灵活地组合对象,使得系统的结构更加松散,各个对象之间的耦合度降低。
1.2 合成与聚合
聚合表示一种弱的 拥有 关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分。
合成则是一种强的 拥有 关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。
比如说:
大雁有两个翅 膀,翅膀与大雁是部分和整体的关系,并且它们的生命周期是相同的,于是大雁和翅膀就是合成关系。而大雁是群居动物,所以每只大雁都是属于一个 雁群,一个雁群可以有多只大雁,所以大雁和雁群是聚合关系。
又比如:
合成和聚合是两种描述对象间关系的方式,合成表示整体包含部分,它的组成部分不能再单独存在,例如汽车由底盘,发动机,车身等构成。聚合则表示整体与部分之间是一
种“拥有”的关系,部分可以存在于整体之外,例如公司与员工之间的关系。
2、合成/聚合案例说明
假设我们有一个简单的图形绘制程序,需要绘制不同形状的图形,比如矩形和圆形。我们可以使用合成/聚合复用原则来设计这个程序。
2.1 使用合成/聚合复用原则
首先,让我们使用合成/聚合原则来实现这个例子。我们定义一个抽象类Shape,作为所有图形的基类,其中包含一个抽象方法draw()用于绘制图形。然后,我们创建两个具体类Rectangle和Circle,它们分别实现Shape类,并重写draw()方法来实现矩形和圆形的绘制逻辑。
// 图形抽象类:
abstract class Shape {public abstract void draw();
}// 矩形绘制
class Rectangle extends Shape {@Overridepublic void draw() {System.out.println("绘制矩形");}
}// 圆形绘制
class Circle extends Shape {@Overridepublic void draw() {System.out.println("绘制圆形");}
}
接下来,我们可以在绘制程序中使用这些图形类。我们创建一个Drawing类,其中包含一个drawShape()方法,它接收一个Shape对象,并调用draw()方法来绘制图形。
class Drawing {public void drawShape(Shape shape) {shape.draw();}
}
现在,我们可以使用以下代码来绘制矩形和圆形:
public class Main {public static void main(String[] args) {Shape rectangle = new Rectangle();Shape circle = new Circle();Drawing drawing = new Drawing();drawing.drawShape(rectangle); // 绘制矩形drawing.drawShape(circle); // 绘制圆形}
}
通过合成/聚合复用原则,我们通过将
Drawing类与Shape类组合起来,实现了绘制程序的复用和灵活性。我们可以轻松地扩展程序,添加新的图形类,而不需要修改现有的代码。符合了开闭原则
2.2 不使用合成/聚合复用原则
现在,让我们看看如果不使用合成/聚合复用原则,直接使用继承关系来实现这个例子会出现什么问题。
class Rectangle extends Shape {@Overridepublic void draw() {System.out.println("绘制矩形");}
}class Circle extends Rectangle {@Overridepublic void draw() {System.out.println("绘制圆形");}
}
在这个例子中,我们将圆形类直接继承自矩形类,这样的设计违反了合成/聚合复用原则。虽然代码看起来似乎工作正常,但这种设计存在一些问题。
首先,这种设计导致圆形与矩形之间存在不必要的继承关系。圆形并不是一种特殊的矩形,它们的行为和属性是不同的。这样的继承关系破坏了类的单一职责原则和 Liskov替换原则,增加了代码的复杂性和维护成本。
其次,如果我们想要添加其他形状,比如三角形或椭圆形,我们将不得不在继承关系中继续扩展,比如创建一个Triangle类继承自Shape,或者创建一个Ellipse类继承自Circle,这样的扩展会导致类的层级结构变得复杂,难以管理和扩展。
另外,使用继承关系来实现不同形状的绘制逻辑,限制了我们在运行时动态地改变图形的行为。例如,如果我们想要在运行时切换一个图形的绘制方式,使用继承关系就无法实现这种灵活性。
综上所述,如果不使用合成/聚合复用原则,直接使用继承关系来实现图形绘制程序,会导致类之间的耦合度增加,继承关系的滥用,限制了系统的灵活性和扩展性。而使用合成/聚合复用原则,通过组合对象,可以实现更松散的耦合,更灵活的设计和扩展,使得代码更易于维护和修改。
3、合成/聚合复用原则(CARP)的总结
合成/聚合复用原则的优点:
- 降低耦合性:通过使用合成/聚合关系而不是继承关系,可以减少类之间的依赖性,降低系统的耦合度。
- 提高灵活性:合成/聚合关系允许在运行时动态地组合对象,使得系统更加灵活,可以根据需要进行组合和重组。
- 支持扩展和修改:使用合成/聚合关系可以轻松地添加、修改或替换组件,而不会对现有的代码产生影响,提高了系统的可维护性和可扩展性。
- 遵循单一职责原则:合成/聚合关系使得每个类都可以专注于自己的职责,提高了类的内聚性和可读性。
合成/聚合复用原则的缺点:
- 增加代码复杂性:使用合成/聚合关系可能需要引入更多的类和接口,增加了代码的复杂性和理解成本。
- 需要更多的设计和管理:合成/聚合关系需要更加细致的设计和管理,以确保正确地组合和使用对象,否则可能导致不必要的复杂性和错误。
合成/聚合复用原则的适用场景:
- 当需要在运行时动态地组合和重组对象,或者需要支持灵活的配置和扩展时,合成/聚合复用原则是非常适用的。
- 当类之间的关系不是"is-a"的继承关系,而是"has-a"的组合关系时,使用合成/聚合关系更加合适。例如,部分-整体的关系、装饰器模式等场景都可以通过合成/聚合关系来实现。
总结来说,CARP原则通过合成/聚合关系来实现代码的复用和灵活性,相比于继承关系,它能够降低代码的耦合性,提高了系统的可维护性和可扩展性。然而,它也会增加代码的复杂性,需要更多的设计和管理。在需要动态组合对象、支持灵活配置和扩展的场景中,CARP原则是一个有价值的指导原则。
相关文章:
Java设计模式七大原则-合成聚合复用原则
🧑💻作者:猫十二懿 ❤️🔥账号:CSDN 、掘金 、个人博客 、Github 🎉公众号:猫十二懿 合成-聚合复用原则 1、合成-聚合复用原则介绍 合成/聚合复用原则(Composition/Aggregatio…...
SOFA Weekly|可信基础设施技术分论坛、Layotto 社区会议回顾与预告、社区本周贡献...
SOFA WEEKLY | 每周精选 筛选每周精华问答,同步开源进展 欢迎留言互动~ SOFAStack(Scalable Open Financial Architecture Stack)是蚂蚁集团自主研发的金融级云原生架构,包含了构建金融级云原生架构所需的各个组件&am…...
Melody 监控(四十九)
当新的世界出现,请立即向他奔去 上一章简单介绍了Spring Boot Actuator详解(四十八), 如果没有看过,请观看上一章 一. JavaMelody 一.一 什么是 Java Melody JavaMelody是一个方便的Java或JavaEE Web 应用程序监控工具。 它允许自动存储由 Web 应用程序的实际操…...
Shell脚本管道符常用搭配命令
1.sort sort命令——以行为单位对文件内容进行排序,也可以根据不同的数据类型来排序比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。 sort [选项] 文件名 cat file | sort [选项] 常用选项 选项作用-n按照数字进行…...
基于html+mysql+Spring+mybatis+Springboot的Springboot宠物医院管理系统
运行环境: 最好是java jdk 1.8,我在这个平台上运行的。其他版本理论上也可以。 IDE环境: Eclipse,Myeclipse,IDEA或者Spring Tool Suite都可以,如果编译器的版本太低,需要升级下编译器,不要弄太低的版本 tomcat服务器环…...
算法模板(3):搜索(5):其他
搜索 模拟退火 模拟退火一个很关键的是,看看枚举到每一个方案是不是可能的。 3167. 星星还是树 在二维平面上有 n 个点,第 i 个点的坐标为 ( x i , y i ) (x_i,y_i) (xi,yi)。请你找出一个点,使得该点到这 n 个点的距离之和最小。这…...
AWS CodeWhisperer 心得体会:安装与使用
大家好,今天我要和大家分享一下我在使用 AWS CodeWhisperer 这个工具时的心得体会。首先,让我们了解一下什么是 AWS CodeWhisperer。 什么是 AWS CodeWhisperer? AWS CodeWhisperer 是一个用于帮助开发者在 AWS 云平台上更轻松地编写、测试…...
高级查询 — 子查询
关于嵌套查询(子查询) 1.概述 子查询是在一个查询中嵌套另一个查询的查询语句。内部查询从外部查询或数据库中提取数据,然后使用这些数据来执行内部查询。出现在其他语句中的 select 语句,称为嵌套查询或子查询。外部的查询语句…...
霍夫变换(Hough Transform)
文章目录 1. 什么是霍夫变换2. 霍夫直线检测2.1 霍夫直线检测的具体步骤2.2 霍夫直线检测的优缺点2.3 OpenCV中霍夫直线检测的应用2.3.1 标准霍夫检测2.3.2 概率霍夫检测 3. 霍夫圆检测4. 源码仓库地址 1. 什么是霍夫变换 霍夫变换(Hough Transform)是图像处理中的一种特征提取…...
【每日挠头算法题(2)】压缩字符串|仅执行一次字符串交换能否使两个字符串相等
文章目录 一、压缩字符串思路 二、仅执行一次字符串交换能否使两个字符串相等思路1:计数法思路2:模拟法 总结 一、压缩字符串 点我直达~ 思路 使用双指针法 大致过程如下: 使用双指针,分别读(read)&…...
V4L2框架解析
和你一起终身学习,这里是程序员Android 经典好文推荐,通过阅读本文,您将收获以下知识点: 一、概览二、流程简介三、关键结构体四、模块初始化五、处理用户空间请求 一、概览 相机驱动层位于HAL Moudle与硬件层之间,借助linux内核驱…...
Trie树模板与应用
文章和代码已经归档至【Github仓库:https://github.com/timerring/algorithms-notes 】或者公众号【AIShareLab】回复 算法笔记 也可获取。 文章目录 Trie树(字典树)基本思想例题 Trie字符串统计code关于idx的理解 模板总结应用 最大异或对分…...
【华为OD统一考试B卷 | 200分】跳格子游戏(C++ Java JavaScript Python)
文章目录 题目描述输入描述输出描述用例C++javajavaScriptpython题目描述 地上共有N个格子,你需要跳完地上所有的格子,但是格子间是有强依赖关系的,跳完前一个格子后,后续的格子才会被开启,格子间的依赖关系由多组steps数组给出,steps[0]表示前一个格子,steps[1]表示st…...
该选哪个语言进修呢?
前言: 如今,计算机编程已经成为了许多工作领域中的必备技能。但是,现在的计算机语言有很多,这可能会让我们感到困惑:我应该从哪个语言开始呢?在这篇博客中,我们将详细分析当前流行的一些计算机…...
数据库实验三 数据查询一
任务描述 本关任务:按条件查询数据表的所有字段 为了完成本关任务,你需要掌握: 如何查询数据表的所有字段 相关知识 查询数据表 命令格式: select * from 数据表 where 查询条件 任务要求 打开province数据库 第一题 查询街…...
【Python百日进阶-Web开发-Peewee】Day244 - 数据库 Postgresql、CockroachDB
文章目录 六、数据库6.1 初始化数据库6.2 使用 Postgresql6.2.1 隔离级别 6.3 使用 CockroachDB 六、数据库 http://docs.peewee-orm.com/en/latest/peewee/database.html PeeweeDatabase对象表示与数据库的连接。该类Database使用打开数据库连接所需的所有信息进行实例化&…...
Vue 中的列表渲染
Vue 中的列表渲染 在 Vue 中,列表渲染是非常常见的操作。它允许我们将一个数组中的数据渲染为一个列表,从而实现数据的展示和交互。在本文中,我们将探讨 Vue 中的列表渲染的基本原理和用法,并给出一些实例代码来帮助读者更好地理…...
java 中的关键字
1. 面向对象编程(OOP) - 把程序中的实体看做对象,而不是过程或函数。OOP有3个基本特征:封装,继承和多态。 2. 类(Class) - 一个用于描述对象属性和方法的蓝图。 3. 对象(Object) - 类的实例化,也就是一个具体的实体。 4. 方法(Met…...
python序列化和结构化数据详解
序列化和结构化数据是计算机程序中非常重要的概念,它们的原理和应用在许多应用程序中都是必不可少的。Python作为一种高级编程语言,在序列化和结构化数据方面提供了很多优秀的解决方案。在本文中,我们将详细介绍Python中序列化和结构化数据的…...
PoseiSwap的趋势性如何体现?
DEX 代表了一种先进的意识形态,相对于 CEX 其更强调无许可、去中心化以及公开透明。然而随着 DeFi 赛道逐渐从 2021 年年底的高峰逐渐转向低谷,DEX 整体的交易量、TVL等数据指标也开始呈现下滑的趋势,DEX 正在面临发展的新瓶颈期。 在这样的背…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...
MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释
以Module Federation 插件详为例,Webpack.config.js它可能的配置和含义如下: 前言 Module Federation 的Webpack.config.js核心配置包括: name filename(定义应用标识) remotes(引用远程模块࿰…...
es6+和css3新增的特性有哪些
一:ECMAScript 新特性(ES6) ES6 (2015) - 革命性更新 1,记住的方法,从一个方法里面用到了哪些技术 1,let /const块级作用域声明2,**默认参数**:函数参数可以设置默认值。3&#x…...
