当前位置: 首页 > news >正文

设计模式:桥接模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)

上一篇《适配器模式》                                                                 下一篇《装饰器模式》

简介:

桥接模式,它是一种结构型设计模式,它的主要目的是将抽象部分与具体实现部分分离,使它们都可以独立地变化。桥接模式通过使用封装、聚合及继承等行为让不同的类承担不同的职责,从而把抽象(Abstraction)与行为实现(Implementation)分离开来,以保持各部分的独立性以及应对他们的功能扩展。

桥接模式的结构包括以下主要角色:
1、抽象类(AbstractClass):定义了抽象接口,并实现了部分功能。
2、具体实现类(ConcreteClass):实现了抽象类所定义的具体接口,完成抽象类的功能实现。
3、桥接类(BridgeClass):将抽象类和具体实现类连接起来,使得它们可以独立地变化。

桥接模式的使用场景:
1、系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系。此时,可以通过桥接模式使他们在抽象层建立一个关联关系。
2、系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时。
3、一个类存在两个独立变化的维度,而这两个维度都需要进行扩展。

桥接模式的创建步骤:
1、创建抽象类(AbstractClass),它定义了抽象接口,并实现了部分功能。
2、创建具体实现类(ConcreteClass),它实现了抽象类所定义的具体接口,完成抽象类的功能实现。
3、创建桥接类(BridgeClass),它将抽象类和具体实现类连接起来,使得它们可以独立地变化。

桥接模式的优点,主要包括:
1、分离抽象及其实现部分:桥接模式通过将抽象部分与实现部分分离,使得它们可以独立地变化。这种分离有助于降低对实现部分编译时刻的依赖性,当改变一个实现类时,并需要重新编译抽象类和它的客户程序。同时,接口与实现分离有助于分层,从而产生更好的结构化系统,系统的高层部分仅需知道抽象类和具体实现类即可。
2、提高可扩充性:桥接模式使得抽象类和具体实现类可以独立地变化,因此可以独立地对它们进行扩展。这种扩展能力有助于提高系统的可维护性和可重用性。
3、优秀的扩展能力:桥接模式使得抽象类和具体实现类可以独立地变化,因此可以灵活地添加新的具体实现类,以满足新的需求。这种扩展能力使得系统能够适应未来的变化和发展。

总之,桥接模式通过将抽象部分与实现部分分离,提高了系统的可维护性、可重用性和可扩展性,同时降低了系统的复杂性。

桥接模式的缺点,主要包括:
1、增加了系统的理解和设计难度。由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行设计与编程,正确识别出系统中两个独立变化的维度并不容易。
2、可能增加系统的复杂性。对于一些不希望使用继承或因为多层继承导致系统类的个数剧增的场景,可能需要考虑使用桥接模式,这会增加系统的复杂性和理解难度。

总之,桥接模式虽然可以提高系统的可维护性、可重用性和可扩展性,但也增加了系统的复杂性和理解难度。因此,在使用桥接模式时需要权衡其优缺点,根据实际需求进行选择。

示例:

一、C#桥接模式

以下是一个示例,展示了如何在C#中实现桥接模式:

using System;  namespace BridgePatternExample  
{  // 抽象类  public abstract class Abstraction  {  protected Implementor implementor;  public void SetImplementor(Implementor implementor)  {  this.implementor = implementor;  }  public abstract void Operation();  }  // 具体实现类  public class ConcreteAbstraction : Abstraction  {  public override void Operation()  {  implementor.Operation();  }  }  // 实现接口  public interface Implementor  {  void Operation();  }  // 具体实现类1  public class ConcreteImplementor1 : Implementor  {  public void Operation()  {  Console.WriteLine("Concrete Implementor 1 operation");  }  }  // 具体实现类2  public class ConcreteImplementor2 : Implementor  {  public void Operation()  {  Console.WriteLine("Concrete Implementor 2 operation");  }  }class Program  {  static void Main(string[] args)  {  Abstraction abstraction = new ConcreteAbstraction();  abstraction.SetImplementor(new ConcreteImplementor1()); // 第一个实现类操作  abstraction.Operation(); // 输出 "Concrete Implementor 1 operation"  abstraction.SetImplementor(new ConcreteImplementor2()); // 第二个实现类操作  abstraction.Operation(); // 输出 "Concrete Implementor 2 operation"  }   }   
}

二、java桥接模式

桥接模式通常通过以下方式实现:

// 抽象类  
public abstract class AbstractClass {  protected Implementor implementor;  public void setImplementor(Implementor implementor) {  this.implementor = implementor;  }  public abstract void operation();  
}  // 具体实现类  
public class ConcreteClass extends AbstractClass {  @Override  public void operation() {  implementor.operation();  }  
}  // 实现接口  
public interface Implementor {  void operation();  
}  // 具体实现类1  
public class ConcreteImplementor1 implements Implementor {  @Override  public void operation() {  System.out.println("Concrete Implementor 1 operation");  }  
}  // 具体实现类2  
public class ConcreteImplementor2 implements Implementor {  @Override  public void operation() {  System.out.println("Concrete Implementor 2 operation");  }  
}//在客户端中创建上下文对象并注入具体策略对象
public class Main {  public static void main(String[] args) {  AbstractClass abstraction = new ConcreteClass();  abstraction.setImplementor(new ConcreteImplementor1()); // 第一个实现类操作  abstraction.operation(); // 输出 "Concrete Implementor 1 operation"  abstraction.setImplementor(new ConcreteImplementor2()); // 第二个实现类操作  abstraction.operation(); // 输出 "Concrete Implementor 2 operation"}
}

三、javascript桥接模式

在JavaScript中,桥接实现方式如下:

// 抽象类  
class AbstractClass {  constructor(bridge) {  this.bridge = bridge;  }  operation() {  this.bridge.implementationOperation();  }  
}  // 具体实现类  
class ConcreteClass1 {  implementationOperation() {  console.log('ConcreteClass1 operation');  }  
}  class ConcreteClass2 {  implementationOperation() {  console.log('ConcreteClass2 operation');  }  
}  // 桥接类  
class BridgeClass extends AbstractClass {  constructor(implementation) {  super(implementation);  }  
}const bridge1 = new BridgeClass(new ConcreteClass1());  
const bridge2 = new BridgeClass(new ConcreteClass2());  bridge1.operation(); // 输出 "ConcreteClass1 operation"  
bridge2.operation(); // 输出 "ConcreteClass2 operation"

四、C++桥接模式

以下是在C++中实现桥接模式:

#include <iostream>  // 抽象类  
class AbstractClass {  
public:  virtual void operation() = 0;  
};  // 具体实现类1  
class ConcreteClass1 : public AbstractClass {  
public:  void operation() override {  std::cout << "ConcreteClass1 operation" << std::endl;  }  
};  // 具体实现类2  
class ConcreteClass2 : public AbstractClass {  
public:  void operation() override {  std::cout << "ConcreteClass2 operation" << std::endl;  }  
};  // 桥接类  
class BridgeClass {  
public:  AbstractClass* abstract;  BridgeClass(AbstractClass* a) : abstract(a) {}  void operation() { abstract->operation(); }  
};  int main() {  AbstractClass* a = new ConcreteClass1(); // 使用具体实现类1创建抽象类的对象  BridgeClass b(a); // 使用桥接类与抽象类的对象进行交互  b.operation(); // 输出 "ConcreteClass1 operation"  delete a; // 释放内存  a = new ConcreteClass2(); // 使用具体实现类2创建抽象类的对象  b.operation(); // 输出 "ConcreteClass2 operation"  delete a; // 释放内存  return 0;  
}

五、python桥接模式

以下是在python中实现桥接模式:

from abc import ABC, abstractmethod  # 抽象类  
class AbstractClass(ABC):  @abstractmethod  def operation(self):  pass  # 具体实现类1  
class ConcreteClass1(AbstractClass):  def operation(self):  print("ConcreteClass1 operation")  # 具体实现类2  
class ConcreteClass2(AbstractClass):  def operation(self):  print("ConcreteClass2 operation")  # 桥接类  
class BridgeClass:  def __init__(self, abstract_class):  self.abstract_class = abstract_class  def operation(self):  self.abstract_class.operation()  # 使用示例:  
bridge1 = BridgeClass(ConcreteClass1())  
bridge2 = BridgeClass(ConcreteClass2())  
bridge1.operation() # 输出 "ConcreteClass1 operation"  
bridge2.operation() # 输出 "ConcreteClass2 operation"

六、go桥接模式

以下是一个示例,展示了如何在go中实现桥接模式:

package main  import "fmt"  // 抽象类  
type AbstractClass struct {  BridgeClass  
}  func (ac *AbstractClass) Operation() {  ac.BridgeClass.Operation()  
}  // 具体实现类1  
type ConcreteClass1 struct{}  func (cc1 *ConcreteClass1) Operation() {  fmt.Println("ConcreteClass1 operation")  
}  // 具体实现类2  
type ConcreteClass2 struct{}  func (cc2 *ConcreteClass2) Operation() {  fmt.Println("ConcreteClass2 operation")  
}  // 桥接类  
type BridgeClass struct {  impl interface{}  
}  func (bc *BridgeClass) Operation() {  bc.impl.Operation()  
}  func main() {  abstract := &AbstractClass{&BridgeClass{&ConcreteClass1{}}}  abstract.Operation() // 输出 "ConcreteClass1 operation"  abstract.BridgeClass.impl = &ConcreteClass2{}  abstract.Operation() // 输出 "ConcreteClass2 operation"  
}

七、PHP桥接模式

以下是一个示例,展示了如何在PHP中实现桥接模式:

<?php  // 抽象类  
abstract class AbstractClass {  protected $bridge;  public function __construct(BridgeClass $bridge) {  $this->bridge = $bridge;  }  abstract public function operation();  
}  // 具体实现类1  
class ConcreteClass1 implements AbstractClass {  public function operation() {  echo "ConcreteClass1 operation\n";  }  
}  // 具体实现类2  
class ConcreteClass2 implements AbstractClass {  public function operation() {  echo "ConcreteClass2 operation\n";  }  
}  // 桥接类  
class BridgeClass {  protected $implementation;  public function __construct(Implementation $implementation) {  $this->implementation = $implementation;  }  public function operation() {  $this->implementation->operation();  }  
}  // 使用示例:  
$bridge1 = new BridgeClass(new ConcreteClass1());  
$bridge2 = new BridgeClass(new ConcreteClass2());  
$bridge1->operation(); // 输出 "ConcreteClass1 operation"  
$bridge2->operation(); // 输出 "ConcreteClass2 operation"


《完结》

上一篇《适配器模式》                                                               下一篇《装饰器模式》          

相关文章:

设计模式:桥接模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)

上一篇《适配器模式》 下一篇《装饰器模式》 简介&#xff1a; 桥接模式&#xff0c;它是一种结构型设计模式&#xff0c;它的主要目的是将抽象部分与具体实现部分分离&#xff0c;使它们都可以独立地变化。…...

error: the following arguments are required: --model, --data 解决方法

错误原因&#xff1a;Windows下需要缺乏配置参数&#xff0c;需要进行相关参数配置。 解决办法&#xff1a;在Pycharm的编辑设置&#xff0c;加上–model--model ****,其中****为指定的模型名称&#xff0c;按照自己实际报错进行添加&#xff0c;比如我这里要跑的模型为bert&am…...

Kafka - 消息队列的两种模式

文章目录 消息队列的两种模式点对点模式&#xff08;Point-to-Point&#xff0c;P2P&#xff09;发布/订阅模式&#xff08;Publish/Subscribe&#xff0c;Pub/Sub&#xff09; 小结 消息队列的两种模式 消息队列确实可以根据消息传递的模式分为 点对点模式发布/订阅模式 这两…...

【Go】格式化字符串指令大全 Redis常用命令

【Go】格式化字符串指令大全 && Redis常用命令 原创&#xff1a;As.Kai 博客地址&#xff1a;https://blog.csdn.net/qq_42362997 如果以下内容对您有帮助&#xff0c;点赞点赞点赞~ 目录 格式化格式化字符串指令大全%s 用于插入字符串%d 用于插入整数%f 用于插入浮点数…...

Windows 和 Linux 这2个系统在进行编程实现的时候的一些区别:

很惭愧&#xff0c;学了很多年才意识到&#xff0c;噢&#xff0c;原来这两个系统实现一些功能的时候会使用到不同的库&#xff0c;使用不同的函数。 那么&#xff0c;也会延伸出一些问题&#xff1a; 比如&#xff0c;如何实现版本的迁移。一个在Linux上运行的代码如何可以比…...

[SQL开发笔记]SQL 别名:为表名称或列名称指定别名

一、功能描述&#xff1a; 通过使用 SQL&#xff0c;可以为表名称或列名称指定别名。基本上&#xff0c;创建别名是为了让列名称的可读性更强。 二、SQL 别名语法详解&#xff1a; &#xff08;1&#xff09;列的 SQL 别名语法&#xff1a; Select column_name AS alias_nam…...

风险管理案例题

本文摘抄自江山老师高项文档 规划风险 管理 1 、 没进行规划风险管理 2 、 风险管理计划编制存在问题 &#xff0c; 独自一人完成而没有邀请项目组其他成员参与 3 、 仅仅参照以前的项目模板编制风险管理计划 4 、 风险管理计划没有经过项目组讨论直接签字下发实施 &#xf…...

NFC读卡器ST25R3911B-AQWT、ST25R3917B-AQET、ST25R3919B-AQET产品描述、功能框图

一、ST25R3911B 1.4 W功耗可支持VHBR和AAT的高性能HF读卡器 / NFC发起设备 ST25R3911B 是高度集成的NFC发起设备 / HF读卡器IC&#xff0c;包括模拟前端&#xff08;analog front end&#xff0c;AFE&#xff09;和一个高度集成的数据帧系统&#xff0c;可用于ISO 18092&#…...

JVM进阶(2)

一)方法区: java虚拟机中有一个方法区&#xff0c;该区域被所有的java线程都是共享&#xff0c;虚拟机一启动&#xff0c;运行时数据区就被开辟好了&#xff0c;官网上说了方法区可以不压缩还可以不进行GC&#xff0c;JAVA虚拟机就相当于是接口&#xff0c;具体的HotSpot就是虚…...

2023大湾区杯粤港澳金融数学建模竞赛思路+模型+代码

目录 一.思路模型见文末名片&#xff0c;比赛开始第一时间更新 二.大湾区杯常用算法之主成分分析法(PCA) 三.MATLAB代码 四.国赛建模思路获取见此 一.思路模型见文末名片&#xff0c;比赛开始第一时间更新 二.大湾区杯常用算法之主成分分析法(PCA) 主成分分析法(PCA)是一种…...

【Note详细图解】中缀表达式如何转为后缀表达式?数据结构

中缀表达式 中缀表达式&#xff08;中缀记法&#xff09;是一个通用的算术或逻辑公式表示方法&#xff0c;操作符是以中缀形式处于操作数的中间&#xff08;例&#xff1a;3 4&#xff09;&#xff0c;中缀表达式是人们常用的算术表示方法。 前缀或后缀记法不同的是&#xf…...

常用到的资源共享网站

1 资源共享 比你优秀的人都比你努力,你有什么理由不去努力。基础来自己的累秒累天累月的积累 没有一个人是从天而降的天才,也没有哪个人想做一个一生贫庸的人。今天我想说受人以鱼 不如受人以渔。 2 Java 开发软件的官网总结如下: Oracle Java 官网(https://www.oracle.com…...

关于JAVA中字节码文件版本号、产品版本号及开发版本号的关系

目录 关于字节码版本对应关系清单关于字节码格式说明的资料关于这些版本号 关于字节码版本 以二进制打开字节码文件&#xff1a; 如上图中第5-8标识&#xff08;圈起来的&#xff09;的即字节码版本号 十六进制&#xff1a; 34 十进制&#xff1a; 52 jdk 8 对应关系清单 …...

ModbusTCP 转 Profinet 主站网关在博图配置案例

兴达易控ModbusTCP转Profinet网关&#xff0c;在 Profinet 侧做为 Profinet 主站控制器&#xff0c;接 Profinet 设备&#xff0c;如伺服驱动器&#xff1b;兴达易控ModbusTCP 和 Profinet网关在 ModbusTCP 侧做为 ModbusTCP 从站&#xff0c;接 PLC、上位机、wincc 屏等。 拓…...

抖音上怎么挂小程序?制作小程序挂载抖音视频

公司企业商家现在已经把抖音作为营销的渠道之一&#xff0c;目前抖音支持短视频挂载小程序&#xff0c;可方便做营销。以下给大家分享这一操作流程。 一、申请自主挂载能力 首先需要在抖音开放平台官网注册一个抖音小程序账号&#xff0c;然后申请短视频自主挂载能力。 二、搭…...

AI新能量!FortiGate NGFW面向数据中心全面集成FortiGuard AI 安全服务

企业IT技术正在以惊人的速度发展&#xff0c;转型最大的领域之一是下一代防火墙&#xff08;NGFW&#xff09;市场。如今&#xff0c;混合云、多云、边缘等多种基础设施形态共存&#xff0c;已经成为大部分企业的常态&#xff0c;不断扩张的攻击面需要不同形态防火墙的安全防护…...

Git总结

Git介绍 一、Git常用命令 添加、提交 git add 将文件从工作区添加到暂存区&#xff0c;表示git开始追踪文件&#xff0c;如果不想让git追踪了&#xff0c;可以使用 git rm --cached <file> 取消文件追踪&#xff0c;仅仅只代表追踪取消&#xff0c;工作区文件还是照…...

初级前端面试题(一) 之 html/css/js

目 录 一、 HTML 1. .如何理解HTML语义化的&#xff1f; 2. HTML标签有哪些&#xff1f; 3. Canvas 和SVG的区别 二、CSS 1. BFC是什么&#xff1f; 2. 如何实现垂直居中&#xff1f; 3. css选择器 优先级如何确定&#xff1f; 4. 如何清除浮动&#xff1f; 5. …...

python实现excel的数据提取

一文带你实现excel表格的数据提取 今天记录一下如何使用python提取Excel中符合特定条件的数据 在数据处理和分析的过程中&#xff0c;我们经常需要从Excel表格中提取特定条件下的数据。Python的pandas库为我们提供了方便的方法来进行数据查询和过滤。 Pandas 是 Python 语言…...

Vue的MVVM实现原理

目录 前言 用法 代码和效果图 效果图 理解 高质量的使用 前言 MVVM是Model-View-ViewModel的缩写&#xff0c;是一种软件架构设计模式。Vue.js实现了这种设计模式&#xff0c;通过双向数据绑定和虚拟DOM技术&#xff0c;使得数据和视图能够快速响应彼此的变化。了解Vue的…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...

uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)

UniApp 集成腾讯云 IM 富媒体消息全攻略&#xff08;地理位置/文件&#xff09; 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型&#xff0c;核心实现方式&#xff1a; 标准消息类型&#xff1a;直接使用 SDK 内置类型&#xff08;文件、图片等&#xff09;自…...