文章目录

    • 1. 桥接模式概述
    • 2. 模式结构
    • 3. 桥接模式的优缺点
      • 优点
      • 缺点
    • 4. 桥接模式的应用场景
    • 5. C#代码示例
      • 5.1 简单示例 - 形状与颜色
      • 5.2 更复杂的示例 - 跨平台消息发送系统
    • 6. 桥接模式与其他模式的比较
    • 7. 真实世界中的桥接模式应用
      • 7.1 数据库驱动
      • 7.2 UI框架中的渲染机制
    • 8. 桥接模式的实现步骤
    • 9. 桥接模式在实际项目中的注意事项
    • 10. 总结
    • 学习资源

1. 桥接模式概述

桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立变化。这种模式涉及到一个接口作为桥接,使得实体类的功能独立于接口实现类,两者可以独立地变化。

桥接模式的核心思想是:将抽象与实现解耦,使两者可以独立地变化。这种模式通过提供抽象和实现之间的桥接结构,来实现两者的解耦。

2. 模式结构

桥接模式主要包含以下核心角色:

桥接 >
Abstraction
Implementor implementor
Operation()
RefinedAbstraction
Operation()
Implementor
OperationImpl()
ConcreteImplementorA
OperationImpl()
ConcreteImplementorB
OperationImpl()
  • 抽象(Abstraction):定义抽象类的接口,它包含一个指向实现者的引用
  • 扩展抽象(RefinedAbstraction):扩展抽象类接口
  • 实现者接口(Implementor):定义实现类的接口,该接口不必与抽象类的接口完全一致
  • 具体实现者(ConcreteImplementor):实现实现者接口并定义具体实现

3. 桥接模式的优缺点

优点

  1. 分离抽象接口及其实现部分:桥接模式使用"对象间的关联关系"解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。
  2. 提高系统的可扩展性:在两个变化维度中任意扩展一个维度,都不需要修改原有系统,符合"开闭原则"。
  3. 实现细节对客户透明:客户端不用关心实现细节,可以一致性地使用接口。

缺点

  1. 增加系统的理解与设计难度:由于聚合关系建立在抽象层,要求开发者针对抽象进行设计与编程。
  2. 需要正确地识别出系统中两个独立变化的维度:如果识别不正确,可能导致系统设计的复杂性提高。

4. 桥接模式的应用场景

以下是适合使用桥接模式的典型场景:

  1. 不希望在抽象和实现之间有固定的绑定关系:例如,需要在运行时切换不同的实现。
  2. 类的抽象以及它的实现都应该可以通过生成子类的方式加以扩充:这时桥接模式使你可以对不同的维度进行组合扩充,而不是针对每种组合都独立扩展。
  3. 对一个抽象的实现部分的修改应对客户不产生影响:客户端代码不必重新编译。
  4. 有大量的类需要管理:使用桥接模式可以将多层继承结构改为多个正交类层次结构。

常见应用场景包括:

  • 跨平台应用程序(如GUI系统对不同操作系统的支持)
  • 多种数据库驱动程序
  • 不同类型的设备驱动程序
  • 多种渲染引擎的图形系统

5. C#代码示例

5.1 简单示例 - 形状与颜色

下面是一个使用桥接模式实现不同形状和不同颜色组合的示例:

using System;// 实现者接口 - 颜色
public interface IColor
{string Fill();
}// 具体实现者A - 红色
public class Red : IColor
{public string Fill(){return "红色填充";}
}// 具体实现者B - 蓝色
public class Blue : IColor
{public string Fill(){return "蓝色填充";}
}// 抽象 - 形状
public abstract class Shape
{// 桥接:引用实现者接口protected IColor color;// 构造函数注入实现者public Shape(IColor color){this.color = color;}// 抽象操作,由子类实现public abstract void Draw();
}// 扩展抽象A - 圆形
public class Circle : Shape
{private int radius;public Circle(int radius, IColor color) : base(color){this.radius = radius;}public override void Draw(){// 使用桥接的实现者Console.WriteLine($"画一个半径为{radius}的圆,使用{color.Fill()}");}
}// 扩展抽象B - 矩形
public class Rectangle : Shape
{private int width;private int height;public Rectangle(int width, int height, IColor color) : base(color){this.width = width;this.height = height;}public override void Draw(){// 使用桥接的实现者Console.WriteLine($"画一个{width}x{height}的矩形,使用{color.Fill()}");}
}// 客户端代码
public class Client
{public static void Main(string[] args){// 创建具体实现者对象IColor red = new Red();IColor blue = new Blue();// 创建扩展抽象对象并将其与具体实现者关联Shape redCircle = new Circle(10, red);Shape blueCircle = new Circle(5, blue);Shape redRectangle = new Rectangle(20, 15, red);Shape blueRectangle = new Rectangle(10, 5, blue);// 调用抽象的操作方法redCircle.Draw();     // 输出:画一个半径为10的圆,使用红色填充blueCircle.Draw();    // 输出:画一个半径为5的圆,使用蓝色填充redRectangle.Draw();  // 输出:画一个20x15的矩形,使用红色填充blueRectangle.Draw(); // 输出:画一个10x5的矩形,使用蓝色填充}
}

5.2 更复杂的示例 - 跨平台消息发送系统

下面是一个使用桥接模式设计的跨平台消息发送系统,支持不同消息类型和不同平台:

using System;// 实现者接口 - 消息发送平台
public interface IMessageSender
{void SendMessage(string message, string recipient);
}// 具体实现者A - 电子邮件发送器
public class EmailSender : IMessageSender
{public void SendMessage(string message, string recipient){// 实际应用中会调用邮件发送APIConsole.WriteLine($"通过电子邮件发送消息给{recipient}{message}");}
}// 具体实现者B - 短信发送器
public class SmsSender : IMessageSender
{public void SendMessage(string message, string recipient){// 实际应用中会调用短信服务APIConsole.WriteLine($"通过短信发送消息给{recipient}{message}");}
}// 具体实现者C - 社交媒体发送器
public class SocialMediaSender : IMessageSender
{private string platform;public SocialMediaSender(string platform){this.platform = platform;}public void SendMessage(string message, string recipient){// 实际应用中会调用特定社交媒体APIConsole.WriteLine($"通过{platform}发送消息给{recipient}{message}");}
}// 抽象 - 消息
public abstract class Message
{// 桥接:引用消息发送平台protected IMessageSender messageSender;// 构造函数注入实现者public Message(IMessageSender messageSender){this.messageSender = messageSender;}// 抽象方法,由子类实现public abstract void Send(string recipient);
}// 扩展抽象A - 文本消息
public class TextMessage : Message
{private string text;public TextMessage(string text, IMessageSender messageSender) : base(messageSender){this.text = text;}public override void Send(string recipient){messageSender.SendMessage(text, recipient);}
}// 扩展抽象B - 紧急消息
public class UrgentMessage : Message
{private string content;public UrgentMessage(string content, IMessageSender messageSender) : base(messageSender){this.content = content;}public override void Send(string recipient){// 紧急消息添加前缀string urgentMessage = "[紧急] " + content;messageSender.SendMessage(urgentMessage, recipient);// 紧急消息可能有额外的处理,如重复发送Console.WriteLine($"紧急消息已发送,系统将在5分钟后再次发送提醒。");}
}// 扩展抽象C - 加密消息
public class EncryptedMessage : Message
{private string content;public EncryptedMessage(string content, IMessageSender messageSender) : base(messageSender){this.content = content;}// 模拟加密方法private string Encrypt(string message){// 实际应用中会使用真正的加密算法return "已加密(" + message + ")";}public override void Send(string recipient){// 发送前对消息进行加密string encryptedContent = Encrypt(content);messageSender.SendMessage(encryptedContent, recipient);}
}// 客户端代码
public class Client
{public static void Main(string[] args){// 创建具体实现者对象IMessageSender emailSender = new EmailSender();IMessageSender smsSender = new SmsSender();IMessageSender wechatSender = new SocialMediaSender("微信");// 创建不同类型的消息,并关联不同的发送平台Message textEmail = new TextMessage("周会通知:明天下午2点", emailSender);Message urgentSms = new UrgentMessage("系统故障,需要立即处理", smsSender);Message encryptedWechat = new EncryptedMessage("账户密码:123456", wechatSender);// 发送消息textEmail.Send("team@company.com");       // 通过电子邮件发送普通文本消息urgentSms.Send("13800138000");            // 通过短信发送紧急消息encryptedWechat.Send("技术小组");          // 通过微信发送加密消息}
}

6. 桥接模式与其他模式的比较

设计模式主要目的与桥接模式的区别
适配器模式使不兼容的接口能够一起工作适配器模式是事后才补救的策略,而桥接模式是事前的策略
装饰器模式向对象动态添加职责装饰器保持接口不变但增强功能,桥接模式则是分离抽象与实现
组合模式将对象组合成树形结构组合模式重在整体与部分的组织,桥接模式重在抽象与实现的分离
策略模式定义一系列算法,使它们可以互换策略模式注重多种算法的切换,桥接模式注重抽象与实现的解耦

7. 真实世界中的桥接模式应用

7.1 数据库驱动

数据库操作中的JDBC API就是桥接模式的典型应用。JDBC API(抽象)与数据库驱动(实现)分离,使得应用程序可以在不同的数据库管理系统间切换。

// 抽象:数据库操作API
public abstract class DbConnection
{protected IDbDriver driver;public DbConnection(IDbDriver driver){this.driver = driver;}public abstract void Connect(string connectionString);public abstract void Execute(string query);public abstract void Close();
}// 实现者接口:数据库驱动
public interface IDbDriver
{void ConnectToDb(string connectionString);void ExecuteQuery(string query);void CloseConnection();
}// 扩展抽象:SQL数据库连接
public class SqlConnection : DbConnection
{public SqlConnection(IDbDriver driver) : base(driver) { }public override void Connect(string connectionString){Console.WriteLine("初始化SQL连接...");driver.ConnectToDb(connectionString);}public override void Execute(string query){driver.ExecuteQuery(query);}public override void Close(){driver.CloseConnection();}
}// 具体实现者A:MySQL驱动
public class MySqlDriver : IDbDriver
{public void ConnectToDb(string connectionString){Console.WriteLine($"使用MySQL驱动连接到数据库:{connectionString}");}public void ExecuteQuery(string query){Console.WriteLine($"MySQL执行查询:{query}");}public void CloseConnection(){Console.WriteLine("关闭MySQL连接");}
}// 具体实现者B:SQL Server驱动
public class SqlServerDriver : IDbDriver
{public void ConnectToDb(string connectionString){Console.WriteLine($"使用SQL Server驱动连接到数据库:{connectionString}");}public void ExecuteQuery(string query){Console.WriteLine($"SQL Server执行查询:{query}");}public void CloseConnection(){Console.WriteLine("关闭SQL Server连接");}
}

7.2 UI框架中的渲染机制

不同操作系统平台上的UI控件渲染也经常使用桥接模式:

// 实现者接口:渲染引擎
public interface IRenderEngine
{void RenderCircle(float x, float y, float radius);void RenderRectangle(float x, float y, float width, float height);void RenderText(float x, float y, string text);
}// 具体实现者A:Windows渲染引擎
public class WindowsRenderEngine : IRenderEngine
{public void RenderCircle(float x, float y, float radius){Console.WriteLine($"使用Windows GDI+渲染圆形:({x},{y}) 半径 {radius}");}public void RenderRectangle(float x, float y, float width, float height){Console.WriteLine($"使用Windows GDI+渲染矩形:({x},{y}) 大小 {width}x{height}");}public void RenderText(float x, float y, string text){Console.WriteLine($"使用Windows字体渲染文本:({x},{y}) \"{text}\"");}
}// 具体实现者B:MacOS渲染引擎
public class MacRenderEngine : IRenderEngine
{public void RenderCircle(float x, float y, float radius){Console.WriteLine($"使用Quartz 2D渲染圆形:({x},{y}) 半径 {radius}");}public void RenderRectangle(float x, float y, float width, float height){Console.WriteLine($"使用Quartz 2D渲染矩形:({x},{y}) 大小 {width}x{height}");}public void RenderText(float x, float y, string text){Console.WriteLine($"使用Core Text渲染文本:({x},{y}) \"{text}\"");}
}// 抽象:控件
public abstract class Control
{protected IRenderEngine renderEngine;protected float x, y;public Control(IRenderEngine renderEngine, float x, float y){this.renderEngine = renderEngine;this.x = x;this.y = y;}public abstract void Draw();public abstract void Resize(float scale);
}// 扩展抽象A:按钮控件
public class Button : Control
{private string text;private float width, height;public Button(IRenderEngine renderEngine, float x, float y, float width, float height, string text) : base(renderEngine, x, y){this.width = width;this.height = height;this.text = text;}public override void Draw(){renderEngine.RenderRectangle(x, y, width, height);renderEngine.RenderText(x + width/4, y + height/2, text);}public override void Resize(float scale){width *= scale;height *= scale;}
}// 扩展抽象B:圆形图标控件
public class CircleIcon : Control
{private float radius;public CircleIcon(IRenderEngine renderEngine, float x, float y, float radius) : base(renderEngine, x, y){this.radius = radius;}public override void Draw(){renderEngine.RenderCircle(x, y, radius);}public override void Resize(float scale){radius *= scale;}
}

8. 桥接模式的实现步骤

实现桥接模式通常遵循以下步骤:

  1. 确定独立变化的维度:识别系统中可以独立变化的两个维度
  2. 设计抽象层次结构:定义一个抽象类来表示第一个维度
  3. 实现抽象层次结构:通过继承抽象类来实现第一个维度的扩展
  4. 设计实现者层次结构:定义一个实现者接口来表示第二个维度
  5. 实现具体的实现者类:创建实现者接口的具体子类
  6. 在抽象类中关联实现者接口:使用组合/聚合将两个维度桥接起来
  7. 客户端使用:客户端代码将抽象部分与其具体实现部分进行组装

9. 桥接模式在实际项目中的注意事项

  1. 正确识别变化维度:桥接模式的核心在于识别出系统中独立变化的两个或多个维度,如果维度识别不准确,可能会导致设计复杂且收益有限。

  2. 抽象层设计:抽象层应该只包含高层功能,具体细节应该委托给实现层处理。避免在抽象层中包含太多实现细节。

  3. 接口一致性:确保实现者接口的设计足够稳定,如果接口需要频繁变动,会导致所有具体实现者都需要相应修改。

  4. 与继承的对比:桥接模式使用对象组合关系代替继承关系,在面对多维度变化时能够避免类爆炸问题。在考虑使用多层继承时,可以考虑是否适合改用桥接模式。

  5. 避免过度设计:如果系统中的变化维度较少或变化不频繁,使用桥接模式可能会导致不必要的复杂性,这时应该考虑更简单的设计方案。

10. 总结

桥接模式是一种强大的结构型设计模式,它通过将抽象部分和实现部分分离,使两者能够独立变化。这种模式在处理多维度变化的系统时特别有用,可以有效避免由于多层继承导致的类爆炸问题。

桥接模式的核心优势在于:

  1. 分离接口及其实现
  2. 提高系统可扩展性
  3. 实现细节对客户端透明
  4. 减少子类的数量

在实际开发中,当我们面对"多个变化维度"这样的复杂问题时,应该考虑使用桥接模式来简化系统设计,提高代码的可维护性和灵活性。特别是在需要处理跨平台应用、多种数据库支持或设备驱动等场景时,桥接模式能够发挥其优势。

学习资源

  1. Design Patterns: Elements of Reusable Object-Oriented Software - GoF经典著作
  2. Head First Design Patterns - 生动易懂的设计模式入门书籍
  3. Refactoring.Guru - Bridge Pattern
  4. C# Design Pattern Essentials
  5. Microsoft Learn - Design Patterns

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/83331.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/83331.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/83331.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SolidWorks建模(U盘)- 多实体建模拆图案例

这个U盘模型并不是一个多装配体,它是一个多实体零件,它是在零件模式下创建的这些多实体的零部件。按右键解除爆炸就可以装配到一起,再按右键爆炸,就能按照之前移动的位置进行炸开 爆炸视图直接展示 模型案例和素材或取&#xff08…

计算机组成原理核心剖析:CPU、存储、I/O 与总线系统全解

引言 在当今数字化时代,计算机已经渗透到我们生活的方方面面,从智能手机到超级计算机,从智能家居到自动驾驶汽车。然而,你是否曾好奇过,这些功能强大的设备内部究竟是如何工作的?是什么让计算机能够执行各种…

SystemVerilog—Interface语法(二)

在SystemVerilog中,接口(interface)是一种封装信号集合、协议逻辑和通信行为的复合结构。其核心定义内容可分为以下十类: 1. 信号声明 基础信号:可定义逻辑(logic)、线网(wire&…

DAY43打卡

浙大疏锦行 kaggle找到一个图像数据集,用cnn网络进行训练并且用grad-cam做可视化 进阶:并拆分成多个文件 fruit_cnn_project/ ├─ data/ # 存放数据集(需手动创建,后续放入图片) │ ├─ train/ …

[蓝桥杯C++ 2024 国 B ] 立定跳远(二分)

题目描述 在运动会上,小明从数轴的原点开始向正方向立定跳远。项目设置了 n n n 个检查点 a 1 , a 2 , ⋯ , a n a_1, a_2, \cdots , a_n a1​,a2​,⋯,an​ 且 a i ≥ a i − 1 > 0 a_i \ge a_{i−1} > 0 ai​≥ai−1​>0。小明必须先后跳跃到每个检查…

LINUX530 rsync定时同步 环境配置

rsync定时代码同步 环境配置 关闭防火墙 selinux systemctl stop firewalld systemctl disable firewalld setenforce 0 vim /etc/selinux/config SELINUXdisable设置主机名 hostnamectl set-hostname code hostnamectl set-hostname backup设置静态地址 cd /etc/sysconfi…

鸿蒙OSUniApp结合机器学习打造智能图像分类应用:HarmonyOS实践指南#三方框架 #Uniapp

UniApp结合机器学习打造智能图像分类应用:HarmonyOS实践指南 引言 在移动应用开发领域,图像分类是一个既经典又充满挑战的任务。随着机器学习技术的发展,我们现在可以在移动端实现高效的图像分类功能。本文将详细介绍如何使用UniApp结合Ten…

【Redis】大key问题详解

目录 1、什么是大key2、大key的危害【1】阻塞风险【2】网络阻塞【3】内存不均【4】持久化问题 3、如何发现大key【1】使用内置命令【2】使用memory命令(Redis 4.0)【3】使用scan命令【4】监控工具 4、解决方案【1】拆分大key【2】使用合适的数据结构【3】…

redis核心知识点

Redis是一种基于内存的数据库,对数据的读写操作都是在内存中完成,因此读写速度非常快,常用于缓存,消息队列、分布式锁等场景。 Redis 提供了多种数据类型来支持不同的业务场景,比如 String(字符串)、Hash(哈希)、 Lis…

vscode不满足先决条件问题的解决——vscode的老版本安装与禁止更新(附安装包)

目录 起因 vscode更新设置的关闭 安装包 结语 起因 由于主包用的系统是centos的,且版本有点老了,再加上vscode现在不支持老版本的,这对主包来说更是雪上加霜啊 但是主包看了网上很多教程,眼花缭乱,好多配置要改&…

如何成为一名优秀的产品经理(自动驾驶)

一、 夯实核心基础 深入理解智能驾驶技术栈: 感知: 摄像头、雷达(毫米波、激光雷达)、超声波传感器的工作原理、优缺点、融合策略。了解目标检测、跟踪、SLAM等基础算法概念。 定位: GNSS、IMU、高精地图、轮速计等定…

【ISAQB大纲解读】信息隐藏指的是什么

在软件架构中,信息隐藏(Information Hiding) 是核心设计原则之一,由 David Parnas 在 1972 年提出。它强调通过限制对模块内部实现细节的访问,来降低系统复杂度、提高可维护性和可扩展性。在 ISAQB 的学习目标&#xf…

网页前端开发(基础进阶2--JS)

前面学习了html与css,接下来学习JS(JavaScript与Java无关)。 web标准(网页标准)分为3个部分: 1.html主要负责网页的结构(页面的元素和内容) 2.css主要负责网页的表现(…

完全移除内联脚本

说明 日期&#xff1a;2025年5月9日。 内联脚本给跨站脚本攻击&#xff08;XSS&#xff09;留了条路。 示例 日期&#xff1a;2025年5月9日。 如下网页文件a.html&#xff1a; <!-- 内联脚本块 --> <script> function handleClick{ alert("Hello")…

[蓝桥杯]约瑟夫环

约瑟夫环 题目描述 nn 个人的编号是 1 ~ nn&#xff0c;如果他们依编号按顺时针排成一个圆圈&#xff0c;从编号是 1 的人开始顺时针报数。 &#xff08;报数是从 1 报起&#xff09;当报到 kk 的时候&#xff0c;这个人就退出游戏圈。下一个人重新从 1 开始报数。 求最后剩…

电子电气架构 --- 如何应对未来区域式电子电气(E/E)架构的挑战?

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

isp中的 ISO代表什么意思

isp中的 ISO代表什么意思 在摄影和图像信号处理&#xff08;ISP&#xff0c;Image Signal Processor&#xff09;领域&#xff0c;ISO是一个用于衡量相机图像传感器对光线敏感度的标准参数。它最初源于胶片摄影时代的 “国际标准化组织&#xff08;International Organization …

第十二节:第五部分:集合框架:Set集合的特点、底层原理、哈希表、去重复原理

Set系列集合特点 哈希值 HashSet集合的底层原理 HashSet集合去重复 代码 代码一&#xff1a;整体了解一下Set系列集合的特点 package com.itheima.day20_Collection_set;import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import java.util.…

迈向分布式智能:解析MCP到A2A的通信范式迁移

智能体与外部世界的桥梁之言&#xff1a; 在深入探讨智能体之间的协作机制之前&#xff0c;我们有必要先厘清一个更基础的问题&#xff1a;**单个智能体如何与外部世界建立连接&#xff1f;** 这就引出了我们此前介绍过的 **MCP&#xff08;Model Context Protocol&…

Android Studio 配置之gitignore

1.创建或编辑.gitignore文件 在项目根目录下检查是否已有.gitignore文件。如果没有&#xff0c;创建一个新文件&#xff0c;命名为.gitignore&#xff08;注意文件名前有个点&#xff09;。 添加忽略规则&#xff1a;在.gitignore中添加以下内容&#xff1a; 忽略整个 .idea …