桥接模式
场景
- 电脑
- 电脑类型
- 品牌
如上三个之间的关系,如下图:
存在问题
- 在一个有多种可能会变化的维度的系统中,用
继承
方式会造成类爆炸
,扩展起来不灵活- 每次在一个维度上新增一个具体实现都要增加多个子类为了更加灵活的设计系统
- 我们此时可以考虑使用
桥接模式
实现过程
Brand.java
/**
* 品牌
*
* @author BNTang
* @date 2021/10/12
*/
public interface Brand {
/**
* 出售
*/
void sale();
}
Dell.java
/**
* 戴尔
*
* @author BNTang
* @date 2021/10/12
*/
public class Dell implements Brand {
@Override
public void sale() {
System.out.println("销售Dell电脑");
}
}
HuaWei.java
/**
* 华为
*
* @author BNTang
* @date 2021/10/12
*/
public class HuaWei implements Brand {
@Override
public void sale() {
System.out.println("销售华为电脑");
}
}
Lenovo.java
/**
* 联想
*
* @author BNTang
* @date 2021/10/12
*/
public class Lenovo implements Brand {
@Override
public void sale() {
System.out.println("销售联想电脑");
}
}
Computer.java
/**
* 电脑
*
* @author BNTang
* @date 2021/10/12
*/
public class Computer {
protected Brand brand;
public Computer(Brand brand) {
this.brand = brand;
}
public void sale() {
brand.sale();
}
}
DesktopComputer.java
/**
* 台式电脑
*
* @author BNTang
* @date 2021/10/12
*/
public class DesktopComputer extends Computer {
public DesktopComputer(Brand brand) {
super(brand);
}
@Override
public void sale() {
super.sale();
System.out.println("销售台式机");
}
}
LaptopComputer.java
/**
* 笔记本电脑
*
* @author BNTang
* @date 2021/10/12
*/
public class LaptopComputer extends Computer {
public LaptopComputer(Brand brand) {
super(brand);
}
@Override
public void sale() {
super.sale();
System.out.println("销售笔记本");
}
}
Client.java
/**
* 客户端
*
* @author BNTang
* @date 2021/10/12
*/
public class Client {
public static void main(String[] args) {
// 销售联想的笔记本电脑
Computer laptopComputer = new LaptopComputer(new Lenovo());
laptopComputer.sale();
// 销售神舟的台式机
Computer desktopComputer = new DesktopComputer(new HuaWei());
desktopComputer.sale();
}
}
如上是一个案例,接下来在继续看一个代码如下:
Os.java
/**
* 操作系统
*
* @author BNTang
* @date 2021/10/14
*/
public abstract class Os {
protected PicFile picFile;
public Os(PicFile picFile) {
this.picFile = picFile;
}
/**
* 玩
*
* @param fileName 文件名称
*/
public abstract void play(String fileName);
}
Window.java
/**
* Window 操作系统
*
* @author BNTang
* @date 2021/10/14
*/
public class Window extends Os {
public Window(PicFile picFile) {
super(picFile);
}
@Override
public void play(String fileName) {
picFile.decode(fileName);
}
}
MacOs.java
/**
* mac os操作系统
*
* @author BNTang
* @date 2021/10/14
*/
public class MacOs extends Os {
public MacOs(PicFile picFile) {
super(picFile);
}
@Override
public void play(String fileName) {
picFile.decode(fileName);
}
}
PicFile.java
/**
* @author BNTang
* @program design-pattern-pro
* @date Created in 2021/10/14 014 15:49
* @description 实现化角色
**/
public interface PicFile {
/**
* 解码
*
* @param fileName 文件名称
*/
void decode(String fileName);
}
GifPic.java
/**
* @author BNTang
* @program design-pattern-pro
* @date Created in 2021/10/14 014 15:52
* @description
**/
public class GifPic implements PicFile {
@Override
public void decode(String fileName) {
System.out.println("Gif格式图片解析:" + fileName);
}
}
JpegPic.java
/**
* @author BNTang
* @program design-pattern-pro
* @date Created in 2021/10/14 014 15:50
* @description
**/
public class JpegPic implements PicFile {
@Override
public void decode(String fileName) {
System.out.println("jpeg图片格式解析:" + fileName);
}
}
PngPic.java
/**
* @author BNTang
* @program design-pattern-pro
* @date Created in 2021/10/14 014 15:53
* @description
**/
public class PngPic implements PicFile {
@Override
public void decode(String fileName) {
System.out.println("Png图片格式解析:" + fileName);
}
}
桥接模式定义
将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度
主要角色
抽象化(Abstraction)角色
定义抽象类,并包含一个对实现化对象的引用
扩展抽象化(Refined Abstraction)角色
是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法
实现化(Implementor)角色
定义实现化角色的接口,供扩展抽象化角色调用
具体实现化(Concrete Implementor)角色
给出实现化角色接口的具体实现
UML 图
优缺点
优点
- 桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统
- 比如新增了一个小米品牌,我们只需要再定义一个类实现
Brand
接口即可,其他类不需要发生变化- 实现细节对客户透明
缺点
使用场景
- 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时,就可以使用桥接模式
- 当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时
- 避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系
源码分析
- Driver
- DriverManager
- DriverInfo
在 Java 中通过 Connection 提供给各个数据库一样的操作接口,这里的 Connection 可以看作抽象类。可以说我们用来操作不同数据库的方法都是相同的,不过 MySQL 有自己的 ConnectionImpl 类,同样 Oracle 也有对应的实现类。这里 Driver 和 Connection 之间是通过 DriverManager 类进行桥接的。DriverManager 就是桥接的核心,通过 DriverManager 就可以获取到连接对象,各自厂商有各自的 Driver 和自己的 Connection 然后就是通过 DriverManager 让 Driver 和 Connection 建立关系。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具