Java设计模式 —— 【结构型模式】桥接模式详解
前言
现在有一个需求,需要创建不同的图形,并且每个图形都有可能会有不同的颜色。
首先我们看看用继承来实现:
我们可以发现有很多的类,假如我们再增加一个形状或再增加一种颜色,就需要创建更多的类。
试想,在一个有多种可能会变化的维度的系统中,用继承方式会造成类爆炸,扩展起来不灵活。每次在一个维度上新增一个具体实现都要增加多个子类。为了更加灵活的设计系统,我们此时可以考虑使用桥接模式。
定义:
将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
结构
桥接(Bridge)模式包含以下主要角色:
- 抽象化(Abstraction)角色 : 定义抽象类,并包含一个对实现化对象的引用;
- 扩展抽象化(Refined Abstraction)角色 : 是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法;
- 实现化(Implementor)角色 : 定义实现化角色的接口,供扩展抽象化角色调用;
- 具体实现化(Concrete Implementor)角色 : 给出实现化角色接口的具体实现。
代码演示
我们继续以上述案例做以代码演示:
UML类图:
图形类【抽象化角色、扩展抽象化角色】:
//抽象化角色(包含对实现化角色的引用)
public abstract class Shape {protected String name;protected Color color;public Shape(Color color) {this.color = color;}public void show(){System.out.println(color.show() + name);}
}//扩展抽象化角色
public class Square extends Shape {public Square(Color color) {super(color);name = "正方形";}
}public class Round extends Shape {public Round(Color color) {super(color);name = "圆形";}
}
颜色类【实现化角色 、具体实现化角色 】:
public interface Color {String show();
}public class Green implements Color {@Overridepublic String show() {return "绿色";}
}public class Red implements Color {@Overridepublic String show() {return "红色";}
}
测试:
public class Client {public static void main(String[] args) {Shape roundGreen = new Round(new Green());Shape roundRed = new Round(new Red());Shape squareGreen = new Square(new Green());Shape squareRed = new Square(new Red());roundGreen.show();roundRed.show();squareGreen.show();squareRed.show();}
}
优缺点
优点:
- 实现抽象和实现的分离;
- 桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统;
- 桥接模式替代多层继承方案,可以减少子类的个数,降低系统的管理和维护成本;
- 实现细节对客户透明。
缺点:
- 桥接模式的引入增加了系统的理解和设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计和编程;
- 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围有一定的局限性,即需要有这样的应用场景。
使用场景
- 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时;
- 当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时;
- 当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
相关文章:

Java设计模式 —— 【结构型模式】桥接模式详解
前言 现在有一个需求,需要创建不同的图形,并且每个图形都有可能会有不同的颜色。 首先我们看看用继承来实现: 我们可以发现有很多的类,假如我们再增加一个形状或再增加一种颜色,就需要创建更多的类。 试想…...

MySQL学习之DDL操作
目录 数据库的操作 创建 查看 选择 删除 修改 数据类型 表的创建 表的修改 表的约束 主键 PRIMARY KEY 唯一性约束 UNIQUE 非空约束 NOT NULL 外键约束 约束小结 索引 索引分类 常规索引 主键索引 唯一索引 外键索引 优点 缺点 视图 创建 删除 修改…...

游戏AI实现-寻路算法(A*)
A*(A-star)是一种图遍历和寻路算法,由于其完整性、最优性和最佳效率,它被用于计算机科学的许多领域。给定一个加权图、一个源节点和一个目标节点,该算法将找到从源到目标的最短路径(相对于给定的权重&#…...

spring学习(spring的IoC思想、spring容器、spring配置文件、依赖注入(DI)、BeanProxy机制(AOP))
目录 一、spring-IoC。 (1)spring框架。(诞生原因及核心思想) 1、为什么叫框架? 2、spring框架诞生的技术背景。 (2)控制反转(IoC)。 (3)spring的Bean工厂和IoC容器。 &a…...

谁说C比C++快?
看到这个问题,我我得说:这事儿没有那么简单。 1. 先把最大的误区打破 "C永远比C快" —— 某位1990年代的程序员 这种说法就像"自行车永远比汽车省油"一样荒谬。我们来看个例子: // C风格 char* str (char*)malloc(100…...

GEE+本地XGboot分类
GEE本地XGboot分类 我想做提取耕地提取,想到了一篇董金玮老师的一篇论文,这个论文是先提取的耕地,再做作物分类,耕地的提取代码是开源的。 但这个代码直接在云端上进行分类,GEE会爆内存,因此我准备把数据下…...

OpenCV相机标定与3D重建(24)计算两个二维点集之间的最佳仿射变换矩阵(2x3)函数estimateAffine2D()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 计算两个二维点集之间的最优仿射变换,它计算 [ x y ] [ a 11 a 12 a 21 a 22 ] [ X Y ] [ b 1 b 2 ] \begin{bmatrix} x\\ y\\ \en…...

UIP协议栈 TCP通信客户端 服务端,UDP单播 广播通信 example
文章目录 1. TCP通信 客户端(关键配置)2. TCP 服务端配置3. UDP 点播通信4. UDP 广播通信5. UIP_UDP_APPCALL 里边的处理example6. TCP数据处理 ,UIP_APPCALL调用的函数 UIP_APPCALL TCP的数据都在这个宏定义的函数里进行数据处理的 UDP 数据…...

【NoSQL系列】为什么要使用Redis?
第一次知道Redis是以前准备面试的时候,只知道是用来缓存数据的。随着这几年的工作,对软件的认识从盲人摸象到睁眼看世界。 在常用的软件架构评价模型中,性能、可用性、安全性和可维护性是常见的评价属性,客户总希望系统响应又快有…...

MySQL Explain 分析SQL语句性能
一、EXPLAIN简介 使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈。 (1) 通过EXPLAIN,我们可以分析出以下结果: 表的读取顺序数据读取…...

IIS部署程序https是访问出现403或ERR_HTTP2_PROTOCOL_ERROR
一、说明 在windows server 2016中的IIS程序池里部署一套系统,通过https访问站点,同时考虑到安全问题以及防攻击等行为,就用上了WAF云盾功能,能有效的抵挡部分攻击,加强网站的安全性和健壮性。 应用系统一直能够正常…...

学技术学英文:代码中的锁:悲观锁和乐观锁
本文导读: 1. 举例说明加锁的场景: 多线程并发情况下有资源竞争的时候,如果不加锁,会出现数据错误,举例说明: 业务需求:账户余额>取款金额,才能取钱。 时间线 两人共有账户 …...

青少年编程与数学 02-004 Go语言Web编程 02课题、依赖管理
青少年编程与数学 02-004 Go语言Web编程 02课题、依赖管理 课题摘要:一、项目结构各目录说明: 二、依赖项三、依赖管理任务四、依赖管理步骤1. 初始化Go Modules项目2. 添加依赖3. 指定依赖版本4. 更新依赖5. 清理未使用的依赖6. 离线工作7. 模块隔离8. 可重现构建 …...

MyBatis写法汇总
Mybatis写法汇总 1. 批量操作 1.1 批量插入 <insert id"batchInsert" parameterType"java.util.List">INSERT INTO user (username, password, create_time) VALUES<foreach collection"list" item"item" separator"…...

【Linux学习】十五、Linux/CentOS 7 用户和组管理
文章目录 一、组的管理1.组的创建格式:参数: 2.组的删除格式:参数: 3.组的属性修改格式:参数: 4.查看组的信息①cat /etc/group 命令②getent group 命令③仅显示系统中所有组名 二、用户的管理①超级用户&…...
三维无人机航迹算法的目标函数如何确定
一、定义目标函数 在三维无人机航迹算法中,目标函数的确定通常基于具体的任务需求和飞行约束。以下是一个简单的例子,展示了如何为三维无人机航迹规划定义一个目标函数。 例子:最小化飞行时间和避障的三维无人机航迹规划 1.任务描述:无人机需要从起点飞到终点,同时避开一些…...

uniapp v-tabs修改了几项功能,根据自己需求自己改
根据自己的需求都可以改 这里写自定义目录标题 1.数组中的名字过长,导致滑动异常2.change 事件拿不到当前点击的数据,通过index在原数组中查找得到所需要的id 各种字段麻烦3.添加指定下标下新加红点显示样式 1.数组中的名字过长,导致滑动异常…...

用vscode,进行vue开发
使用Visual Studio Code(VSCode)进行Vue.js开发是一个很好的选择,因为VSCode提供了强大的编辑功能以及丰富的插件生态。以下是使用VSCode进行Vue开发的基本步骤: 1. 安装Node.js和npm 首先,确保你的计算机上安装了No…...

Kafka 磁道寻址过程详解
前言 Apache Kafka 是一款高吞吐、分布式的消息流平台,广泛应用于实时数据处理和事件驱动系统。在 Kafka 中,消息是存储在磁盘上的,这种高效的数据读写性能得益于 Kafka 独特的磁盘存储架构和寻址机制。本文将从 Kafka 的存储结构、磁道寻址…...

基于Spring Boot的社区药房系统
一、系统背景与目的 随着医疗改革的深入和社区医疗服务的不断完善,社区药房在居民健康保障中扮演着越来越重要的角色。然而,传统的药房管理方式存在着库存管理混乱、药品销售不透明、客户信息管理不规范等问题。为了解决这些问题,基于Spring…...

005 QT常用控件Qwidget_上
文章目录 前言控件概述QWidgetenable属性geometry属性windowTitle属性windowlcon属性 小结 前言 本文将会向你介绍常用的Qwidget属性 控件概述 Widget 是 Qt 中的核心概念. 英文原义是 “⼩部件”, 我们此处把它翻译为 “控件” . 控件是构成⼀个图形化界面的基本要素. QWi…...

机器学习之交叉熵
交叉熵(Cross-Entropy)是机器学习中用于衡量预测分布与真实分布之间差异的一种损失函数,特别是在分类任务中非常常见。它源于信息论,反映了两个概率分布之间的距离。 交叉熵的数学定义 对于分类任务,假设我们有&#…...

数据结构 ——前缀树查词典的实现
数据结构 ——前缀树查词典的实现 一、前缀树的概念 前缀树是一种多叉树结构,主要用于存储字符串。每个节点代表一个字符,路径从根节点到叶节点表示一个完整的字符串。前缀树的关键特征是 共享前缀,也就是说,如果两个字符串有相…...

MySQL 主从复制与高可用架构
一、MySQL 主从复制概述 (一)定义与作用 MySQL 主从复制是一种允许在多个 MySQL 数据库服务器之间进行数据同步的技术。简单来说,就是可以把数据从一个 MySQL 服务器(主服务器、主节点)复制到一个或多个从节点&#…...

【Golang】如何读取并解析SQL文件
一、背景 在数据库开发与维护过程中,我们经常需要执行大量的SQL语句。有时,这些SQL语句会被保存在一个文件中,以便于批量执行。为了方便地在Go语言中处理这些SQL文件,我们可以编写一个函数来读取并解析SQL文件中的语句。 二、实…...

git branch -r(--remotes )显示你本地仓库知道的所有 远程分支 的列表
好的,git branch -r 这个命令用于列出远程分支。让我详细解释一下: 命令: git branch -rdgqdgqdeMac-mini ProductAuthentication % git branch -rorigin/main作用: 这个命令会显示你本地仓库知道的所有 远程分支 的列表。它不…...

Typescript安装
建议全局安装npm i -g typescript安装好之后,就可以直接使用 tsc 来编译 ts 文件了可通过 tsc 回车查看 tsc 的各项配置信息,通过 tsc --version 查看版本号。编译我们现在可以创建一个 ts 文件,并将他编译成 js 文件,比如下面简单…...

使用C#在目录层次结构中搜索文件以查找目标字符串
例程以递归方式搜索目录层次结构中的文件以查找目标字符串。它可以搜索几乎任何类型的文件,即使它不包含 Windows 理解的文本。例如,它可以搜索 DLL 和可执行文件以查看它们是否恰好包含字符串。 下面的代码中显示的ListFiles 方法完成了大部分工作。 …...

基于Redis实现令牌桶算法
基于Redis实现令牌桶算法 令牌桶算法算法流程图优点缺点 实现其它限流算法 令牌桶算法 令牌桶是一种用于分组交换和电信网络的算法。它可用于检查数据包形式的数据传输是否符合定义的带宽和突发性限制(流量不均匀或变化的衡量标准)。它还可以用作调度算…...

[Java] 使用 VSCode 来开发 Java
目录 前言Java 环境怎么看自己是否已经配置完成?安装 JDK安装 Maven 环境修改 Maven 依赖源 完善 VS Code配置插件配置 Maven配置 Maven Settings配置 Maven 可执行文件地址 前言 由于使用 VSCode 编码已经成为习惯,并且它确实相对其他的 IDE 较为轻量化…...