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

桥接(桥梁)模式

简介

桥接模式(Bridge Pattern)又叫作桥梁模式、接口(Interface)模式或柄体(Handle and Body)模式,指将抽象部分与具体实现部分分离,使它们都可以独立地变化,属于结构型设计模式。

常用用于替换继成

通用模板

  1. 创建实现接口:确定实现维度的基本操作,提供给Abstraction使用。该类一般为接口或抽象类。

    // 抽象实现
    public interface IImplementor {void operationImp();
    }
    
  2. 创建具体实现类:Implementor的具体实现。

    // 具体实现类A
    public class ConcreteImplementorA implements IImplementor{@Overridepublic void operationImp() {System.out.println("I am ConcreteImplementorA");}
    }
    
    
    // 具体实现类B
    public class ConcreteImplementorB implements IImplementor {@Overridepublic void operationImp() {System.out.println("I am ConcreteImplementorB");}
    }
    
  3. 创建抽象类:该类持有一个对实现角色的引用,抽象角色中的方法需要实现角色来实现。抽象角色一般为抽象类(构造函数规定子类要传入一个实现对象)。

    // 抽象
    public abstract class Abstraction {private IImplementor iImplementor;public Abstraction(IImplementor iImplementor) {this.iImplementor = iImplementor;}public void operation() {iImplementor.operationImp();}
    }
    
  4. 创建修正抽象类:Abstraction的具体实现,对Abstraction的方法进行完善和扩展。

    // 修正抽象类
    public class RefineAbstraction extends Abstraction {public RefineAbstraction(IImplementor iImplementor) {super(iImplementor);}@Overridepublic void operation() {super.operation();System.out.println("refine operation");}
    }
    
  5. 创建修正实现类:RefineAbstraction的具体实现

    // 修正抽象实现类
    public class ConcreteRefineAbstractionA extends RefineAbstraction {public ConcreteRefineAbstractionA(IImplementor iImplementor) {super(iImplementor);}@Overridepublic void operation() {super.operation();System.out.println("ConcreteRefineAbstraction");}
    }
    

模板测试

  1. 测试代码

    public class Client {public static void main(String[] args) {// 创建一个具体的角色ConcreteImplementorA imp = new ConcreteImplementorA();// 创建一个抽象的角色,聚合实现RefineAbstraction abs = new ConcreteRefineAbstractionA(imp);// 执行操作abs.operation();}
    }
    
  2. 结果

    I am ConcreteImplementorA
    refine operation
    ConcreteRefineAbstraction
    

应用场景

在生活场景中,桥接模式随处可见,比如连接起两个空间维度的桥、连接虚拟网络与真实网络的链接。
当一个类内部具备两种或多种变化维度时,使用桥接模式可以解耦这些变化的维度,使高层代码架构稳定。
桥接模式适用于以下几种业务场景。
(1)在抽象和具体实现之间需要增加更多灵活性的场景。
(2)一个类存在两个(或多个)独立变化的维度,而这两个(或多个)维度都需要独立进行扩展。 (3)不希望使用继承,或因为多层继承导致系统类的个数剧增。

注:桥接模式的一个常见使用场景就是替换继承。我们知道,继承拥有很多优点,比如,抽象、封装、多态等,父类封装共性,子类实现特性。继承可以很好地实现代码复用(封装)的功能,但这也是继承的一大缺点。因为父类拥有的方法,子类也会继承得到,无论子类需不需要,这说明继承具备强侵入性(父类代码侵入子类),同时会导致子类臃肿。因此,在设计模式中,有一个原则为优先使用组合/聚合,而不是继承。 很多时候,我们分不清该使用继承还是组合/聚合或其他方式等,其实可以从现实语义进行思考。因为软件最终还是提供给现实生活中的人使用的,是服务于人类社会的,软件是具备现实场景的。当我们从纯代码角度无法看清问题时,现实角度可能会提供更加开阔的思路。

优点

(1)分离抽象部分及其具体实现部分。
(2)提高了系统的扩展性。
(3)符合开闭原则。
(4)符合合成复用原则。

缺点

(1)增加了系统的理解与设计难度。
(2)需要正确地识别系统中两个独立变化的维度。

“生搬硬套”实战

场景描述

桥接模式的定义非常玄乎,直接理解不太容易,所以我们还是举例子。

假设某个汽车厂商生产三种品牌的汽车:Big、Tiny和Boss,每种品牌又可以选择燃油、纯电和混合动力。如果用传统的继承来表示各个最终车型,一共有3个抽象类加9个最终子类:
在这里插入图片描述
如果要新增一个品牌,或者加一个新的引擎(比如核动力),那么子类的数量增长更快。

所以,桥接模式就是为了避免直接继承带来的子类爆炸。

我们来看看桥接模式如何解决上述问题。

在桥接模式中,首先把Car按品牌进行子类化,但是,每个品牌选择什么发动机,不再使用子类扩充,而是通过一个抽象的“修正”类,以组合的形式引入。我们来看看具体的实现。

代码开发
  1. 创建实现(这里指引擎)接口

    // 实现接口
    public interface Engine {void start();
    }
    
  2. 创建具体实现(这里指的是各种引擎)类

    // 混动引擎实现
    public class HybridEngine implements Engine {public void start() {System.out.println("Start Hybrid Engine...");}
    }
    
    // 油引擎实现
    public class FuelEngine implements Engine {public void start() {System.out.println("Start Fuel Engine...");}
    }
    
    // 纯电引擎实现
    public class PureEngine implements Engine {public void start() {System.out.println("Start Pure Engine...");}
    }
    
  3. 创建抽象(这里指的是车)类

    // 抽象车类
    public abstract class Car {// 引用Engine:protected Engine engine;public Car(Engine engine) {this.engine = engine;}public abstract void drive();
    }
    
  4. 创建修正抽象(这里指的是修正车类)类

    // 修正车抽象类
    public abstract class RefinedCar extends Car{public RefinedCar(Engine engine) {super(engine);}@Overridepublic void drive() {this.engine.start();System.out.println("Drive " + getBrand() + " car...");}public abstract String getBrand();
    }
    
  5. 创建修正实现(这里指具体不同品牌的车)类

    // Boss品牌车
    public class BossCar extends RefinedCar {public BossCar(Engine engine) {super(engine);}@Overridepublic String getBrand() {return "Boss";}
    }
    
    // Big品牌车
    public class BigCar extends RefinedCar {public BigCar(Engine engine) {super(engine);}@Overridepublic String getBrand() {return "Big";}
    }
    
    // Tiny品牌车
    public class TinyCar extends RefinedCar {public TinyCar(Engine engine) {super(engine);}@Overridepublic String getBrand() {return "Tiny";}
    }
    

至此,我们就通过“生搬硬套”桥梁模式的模板设计出一套替换继成的桥接模式代码,接下来我们进行测试:

  • 测试代码

    public class Test {public static void main(String[] args) {RefinedCar car = new BossCar(new HybridEngine());car.drive();}
    }
    
  • 结果

    Start Hybrid Engine...
    Drive Boss car...
    

总结

使用桥接模式的好处在于,如果要增加一种引擎,只需要针对Engine派生一个新的子类,如果要增加一个品牌,只需要针对RefinedCar派生一个子类,任何RefinedCar的子类都可以和任何一种Engine自由组合,即一辆汽车的两个维度:品牌和引擎都可以独立地变化。
在这里插入图片描述
桥接模式实现比较复杂,实际应用也非常少,但它提供的设计思想值得借鉴,即不要过度使用继承,而是优先拆分某些部件,使用组合的方式来扩展功能。

相关文章:

桥接(桥梁)模式

简介 桥接模式(Bridge Pattern)又叫作桥梁模式、接口(Interface)模式或柄体(Handle and Body)模式,指将抽象部分与具体实现部分分离,使它们都可以独立地变化,属于结构型…...

语言模型发展史

四个阶段 第一阶段:基于规则和统计的语言模型 由人工设计特征并使用统计方法对固定长度的文本窗口序列进行建模分析,这种建模方式也被称为N-gram语言模型。 优点: 1)采用极大似然估计, 参数易训练 2)完全包含了前n-…...

【Linux】模拟实现一个shell

接受每一个人的批评,可是保留你自己的判断。 ——莎士比亚 一段时间的没有更新是由于最近开学期间比较的忙,同时也是由于刚开学的几门课才学习的时候有点迷糊,需要在学校课堂上花的时间更多了,所以才没有更新的,求放过…...

云原生数据库 PolarDB

简介:云原生数据库 PolarDB 是阿里云自研产品,在存储计算分离架构下,利用了软硬件结合的优势,为用户提供秒级弹性、高性能、海量存储、安全可靠的数据库服务。100%兼容MySQL和PostgreSQL生态,支持分布式扩展&#xff0…...

MobaXterm基本使用 -- 服务器状态、批量操作、显示/切换中文字体、修复zsh按键失灵

监控服务器资源 参考网址:https://www.cnblogs.com/144823836yj/p/12126314.html 显示效果 MobaXterm提供有这项功能,在会话窗口底部,显示服务器资源使用情况 如内存、CPU、网速、磁盘使用等: (完整窗口&#xff0…...

elastic Search 初步之向量检索的数据写入及检索查询

### Elasticsearch 向量检索实现方法方案 Elasticsearch 从 7.3 版本开始引入了向量检索功能,支持通过向量字段进行相似度搜索。以下是实现向量检索的步骤和方案,包括 Python 和 Java 版本的代码示例。 #### 1. 最低实现向量检索的 ES 版本 - **最低版本**: Elasticsearch …...

Tdesign TreeSelect 树形选择 多选

这里写自定义目录标题 小程序原生开发 Tdesign TreeSelect 树形选择 多选可以选择不同一级分类下的数据 小程序原生开发 Tdesign TreeSelect 树形选择 多选可以选择不同一级分类下的数据 TreeSelect 树形选择 在原demo基础上修改 const chineseNumber 一二三四五六七八九十.…...

Pygame中Sprite实现逃亡游戏5

在《Pygame中Sprite实现逃亡游戏4》中通过碰撞检测实现了玩家、飞龙与飞火之间的碰撞处理,基本上实现了逃亡功能。最后,实现这个逃亡游戏中文字提示的功能。 1 操作提示 当进入游戏后,会在玩家下方的位置给出操作提示,如图1所示…...

等保2.0数据库测评之达梦数据库测评

一、达梦数据库介绍 达梦数据库管理系统属于新一代大型通用关系型数据库,全面支持 ANSI SQL 标准和主流编程语言接口/开发框架。行列融合存储技术,在兼顾 OLAP 和 OLTP 的同时,满足 HTAP 混合应用场景。 本次安装环境为Windows10专业版操作…...

集成mcuboot后测试和验证的方法

本文介绍一些在实际项目中集成的 MCUboot后测试和验证的方法和步骤: 功能测试 启动测试 正常启动验证 : 多次上电启动设备,观察 MCUboot 是否能够正常加载并跳转到应用程序。检查启动过程中的日志输出(如果有)&#…...

Vulhub zico 2靶机详解

项目地址 https://download.vulnhub.com/zico/zico2.ova实验过程 将下载好的靶机导入到VMware中,设置网络模式为NAT模式,然后开启靶机虚拟机 使用nmap进行主机发现,获取靶机IP地址 nmap 192.168.47.1-254根据对比可知Zico 2的一个ip地址为…...

宠物医院微信小程序源码

文章目录 前言研究背景研究内容一、主要技术?二、项目内容1.整体介绍(示范)2.系统分析3.数据表信息4.运行截图5.部分代码介绍 总结 前言 随着当代社会科技的迅速发展,计算机网络时代正式拉来帷幕,它颠覆性的影响着社会…...

[教程]Crystal源码下载及编译

描述: 随着 Crystal Source 代码的更新,用于构建源代码和编译它们的指南已经过时,这导致了很多混淆和寻求帮助。 本指南将是一个完整的分步指南,从下载 Visual Studio 到启动到您的服务器。 此外,请确保下载此存储库中…...

【Android 14源码分析】WMS-窗口显示-流程概览与应用端流程分析

忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。                                                                                  – 服装…...

双指针---(部分地更新)

双指针 复写零 给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。 注意:请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。 …...

【Windows】自定义显示器的分辨率

背景 由于本人更新驱动导致2个显示器里面,有一个显示器的分辨率只剩下2个可以调节 这样就导致2个显示器分辨率不同,更新了多次驱动都修复不了,所以想着看能不能自定义分辨率 工具下载 显示器自定义分辨率工具 或者百度搜索 Custom Resolu…...

组播基础-2-IGMP协议

文章目录 IGMPIGMPv1IGMPv2IGMPv3IGMP总结IGMP Snooping IGMP 运行于主机和路由器之间 因特网组管理协议,TCP/IP 协议族中负责 IP 组播成员管理的协议,用来在接收者与其他直接相邻的组播路由器之间建立、维护组播组成员关系 负责组播成员管理&#xf…...

基于Springboot+Vue的视频点播系统设计与实现登录 (含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统中…...

执行力怎么培养?

执行力怎么培养? 并行:适合在初期养成习惯,不抱对结果的期望天才就是强迫症:适合中期修身:适合高级 并行:适合在初期养成习惯,不抱对结果的期望 在你开始做任何事情的时候,不要一开…...

Power apps:一次提交多项申请

1、添加一个Form,导入sharepoint列表,添加确认,继续,取消按钮 2、在页面的onvisible属性中添加 Set(applynumber,Last(付款申请表).申请编号1); #定义一个申请编号变量,每次申请,就将列表最后一个…...

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)&#xff0…...

【JVM】- 内存结构

引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...

Java 加密常用的各种算法及其选择

在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...