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

【设计模式深度剖析】【5】【结构型】【桥接模式】| 以电视和遥控器为例加深理解

👈️上一篇:组合模式

设计模式-专栏👈️

目 录

  • 桥接模式(Bridge Pattern)
  • 定义
    • 英文原话是:
    • 直译
    • 理解
  • 4个角色
    • UML类图
    • 代码示例
  • 应用
    • 优点
    • 缺点
    • 使用场景
  • 示例解析:电视和遥控器
    • UML类图

桥接模式(Bridge Pattern)

定义

英文原话是:

  • Bridge Pattern is a software design pattern that is used to overcome the limitations of the traditional inheritance.
  • It decouples an abstraction from its implementation so that the two can vary independently.
  • The bridge pattern consists of two parts: abstraction and implementation.
  • The abstraction part defines the interface that the client uses to interact with the system.
  • The implementation part implements the abstraction by providing the functionality required by the client.

直译

  • 桥接模式是一种用于克服传统继承局限性的软件设计模式。
  • 它将抽象部分与实现部分解耦,使得两者可以独立地变化
  • 桥接模式由两部分组成:抽象部分和实现部分。
    • 抽象部分定义了客户端与系统交互的接口。
    • 实现部分通过提供客户端所需的功能来实现抽象部分。

理解

桥接模式(Bridge Pattern)从字面上理解,可以想象成一个桥梁连接了两个不同的部分,使得这两个部分可以相互通信或协作,而不需要彼此之间有直接的依赖关系。在软件设计中,这两个部分通常指的是抽象部分和实现部分。

在桥接模式中,抽象部分定义了一个接口(或抽象类),用于定义抽象层的行为。实现部分则实现了这个接口,提供了具体实现。这两个部分通过组合的方式关联在一起,而不是继承。这样做的好处是,抽象部分和实现部分可以独立变化,只要它们遵循相同的接口规范。

桥接模式的主要目的是通过组合的方式建立抽象与实现之间的联系,而不是通过继承。

这允许开发人员在不修改抽象接口的情况下修改实现,从而提高了系统的灵活性和可扩展性。

同时,桥接模式也避免了多重继承可能带来的问题,如违背类的单一职责原则和降低复用性等。

4个角色

桥接模式(Bridge Pattern)是一种结构型设计模式,它将抽象部分与它的实现部分分离,使得它们可以独立地变化。这种类型的设计模式属于结构型模式,它通过提供抽象层和实现层之间的桥接结构,来实现二者的解耦。

UML类图

在这里插入图片描述

桥接模式包含以下四个角色:

  1. 抽象化(Abstraction)角色:定义抽象类的接口,并保存一个对实现化对象的引用。
  2. 扩展抽象化(RefinedAbstraction)角色:抽象化角色的子类,实现它要求的业务逻辑,并通过组合关系调用实现化角色中的业务方法。
  3. 实现化(Implementor)角色:这个接口定义了实现化角色的接口,但不提供具体的实现。这个接口必须被实现化角色的具体类来实现。
  4. 具体实现化(ConcreteImplementor)角色:实现化角色接口的具体实现类。

代码示例

以下是一个Java示例来演示桥接模式:

package com.polaris.designpattern.list2.structural.pattern5.bridge.classicdemo;// 实现化角色接口
interface Implementor {  void operationImpl();  
}  // 具体实现化角色  
class ConcreteImplementorA implements Implementor {  @Override  public void operationImpl() {  System.out.println("操作A的实现");  }  
}  class ConcreteImplementorB implements Implementor {  @Override  public void operationImpl() {  System.out.println("操作B的实现");  }  
}  // 抽象化角色  
abstract class Abstraction {  protected Implementor implementor;  public Abstraction(Implementor implementor) {  this.implementor = implementor;  }  public abstract void operation();  
}  // 扩展抽象化角色  
class RefinedAbstraction extends Abstraction {  public RefinedAbstraction(Implementor implementor) {  super(implementor);  }  @Override  public void operation() {  // 在调用实现化角色的方法之前或之后,可以添加一些逻辑  System.out.println("扩展操作前...");  implementor.operationImpl();  System.out.println("扩展操作后...");  }  
}  // 客户端代码  
public class BridgePatternDemo {  public static void main(String[] args) {  Implementor implementorA = new ConcreteImplementorA();  Abstraction abstraction = new RefinedAbstraction(implementorA);  abstraction.operation();System.out.println("-----------");Implementor implementorB = new ConcreteImplementorB();  abstraction = new RefinedAbstraction(implementorB);  abstraction.operation();  }  
}/* Output:
扩展操作前...
操作A的实现
扩展操作后...
-----------
扩展操作前...
操作B的实现
扩展操作后...
*///~

在这个例子中,Implementor 是实现化角色接口,ConcreteImplementorAConcreteImplementorB 是两个具体实现化角色。Abstraction 是抽象化角色,它持有一个对实现化角色的引用,而 RefinedAbstraction 是扩展抽象化角色,它扩展了 Abstraction 的功能。客户端代码通过组合关系,将实现化角色和抽象化角色组合在一起,实现了二者的解耦。

应用

再来总结下,桥接模式(Bridge Pattern)是一种结构型设计模式,它通过将抽象部分与实现部分解耦,使得它们可以独立地变化。

桥接模式通常用于以下情况:

  1. 抽象和实现需要独立变化:当抽象部分和实现部分都需要独立扩展时,可以使用桥接模式。例如,不同的数据库系统(抽象部分)可能需要不同的驱动程序(实现部分)。
  2. 需要跨多个平台实现:当系统需要在不同的平台上运行时,可以使用桥接模式来封装平台相关的代码。
  3. 避免继承层次过深:当使用继承来实现多个维度的变化时,可能会导致继承层次过深,使得代码难以理解和维护。桥接模式通过组合代替继承,可以解决这个问题。

优点

  1. 分离抽象与实现:桥接模式将抽象部分与实现部分分离,使得它们可以独立地变化。这增加了系统的灵活性和可扩展性。
  2. 减少继承层次:通过组合关系替代继承关系,减少了继承层次,降低了系统的复杂度。
  3. 支持动态切换实现:在运行时,可以动态地切换实现部分,而不需要修改抽象部分的代码。
  4. 符合开闭原则:桥接模式符合开闭原则,即对扩展开放,对修改封闭。当需要添加新的实现时,只需要添加新的实现类,而不需要修改已有的代码。

缺点

  1. 增加了系统的复杂性:由于引入了抽象部分和实现部分两个层次,增加了系统的复杂性。对于简单的系统来说,可能不需要使用桥接模式。
  2. 可能增加了系统开销:在运行时,需要维护抽象部分和实现部分之间的关联关系,这可能会增加一些额外的开销。

使用场景

以下是一些适合使用桥接模式的场景:

  1. 多种操作系统:当软件需要在多种操作系统上运行时,可以使用桥接模式来封装与操作系统相关的代码。这样,只需要编写一次抽象部分的代码,就可以通过更换不同的实现部分来适应不同的操作系统。
  2. 多种数据库系统:当软件需要与多种数据库系统进行交互时,可以使用桥接模式来封装与数据库相关的代码。这样,只需要编写一次抽象部分的代码,就可以通过更换不同的实现部分来适应不同的数据库系统。
  3. 多种图形用户界面:当软件需要支持多种图形用户界面(如Windows、Mac、Linux等)时,可以使用桥接模式来封装与界面相关的代码。这样,只需要编写一次抽象部分的代码,就可以通过更换不同的实现部分来适应不同的界面风格。
  4. 多种网络协议:当软件需要与多种网络协议进行通信时,可以使用桥接模式来封装与网络协议相关的代码。这样,只需要编写一次抽象部分的代码,就可以通过更换不同的实现部分来适应不同的网络协议。

示例解析:电视和遥控器

在生活中,一个常见的桥接模式的例子是电视和遥控器。

电视(抽象化角色)提供了观看节目的基本功能,而遥控器(实现化角色)则负责控制电视的不同操作(如换台、调节音量等)。

电视本身不关心遥控器是如何实现的,只要它符合一定的接口规范(如红外信号、蓝牙等)。

同样,遥控器也可以控制不同类型的电视,只要电视也符合相应的接口规范。

UML类图

在这里插入图片描述

下面是一个简化的代码示例,用于说明这个场景:

package com.polaris.designpattern.list2.structural.pattern5.bridge.remotecontroldemo;//遥控器接口(Implementor)
interface RemoteControl {//换台void changeChannel(int channel);//调节音量void adjustVolume(int volume);// ... 其他控制方法  
}//具体遥控器(ConcreteImplementor)  
class InfraredRemoteControl implements RemoteControl {@Overridepublic void changeChannel(int channel) {System.out.println("使用红外遥控器换台到: " + channel);}@Overridepublic void adjustVolume(int volume) {System.out.println("使用红外遥控器调节音量到: " + volume);}// ... 实现其他控制方法  
}//电视抽象类(Abstraction) 
abstract class Television {protected RemoteControl remoteControl;public Television(RemoteControl remoteControl) {this.remoteControl = remoteControl;}public abstract void turnOn();public abstract void turnOff();// 使用遥控器来控制电视  public void watch() {System.out.println("正在看电视...");remoteControl.changeChannel(10); // 假设切换到10频道  remoteControl.adjustVolume(50); // 假设调节音量到50  }
}//具体电视类(RefinedAbstraction) 
class LEDTelevision extends Television {public LEDTelevision(RemoteControl remoteControl) {super(remoteControl);}@Overridepublic void turnOn() {System.out.println("LED电视已打开");}@Overridepublic void turnOff() {System.out.println("LED电视已关闭");}
}//客户端代码  
public class BridgePatternDemo {public static void main(String[] args) {// 创建一个红外遥控器  RemoteControl infraredRemote = new InfraredRemoteControl();// 创建一个LED电视,并使用红外遥控器  Television ledTv = new LEDTelevision(infraredRemote);ledTv.turnOn(); // 打开电视  ledTv.watch(); // 使用遥控器观看电视  ledTv.turnOff(); // 关闭电视  }
}/* Output:
LED电视已打开
正在看电视...
使用红外遥控器换台到: 10
使用红外遥控器调节音量到: 50
LED电视已关闭
*///~

在这个例子中,Television 是抽象化角色,它定义了电视的基本操作(如打开、关闭),并持有对 RemoteControl(遥控器)的引用。LEDTelevision 是扩展抽象化角色,它扩展了电视的基本功能,并提供了具体的实现。RemoteControl 是实现化角色接口,定义了遥控器需要实现的方法。InfraredRemoteControl 是具体实现化角色,它实现了红外遥控器的功能。

客户端代码创建了一个 InfraredRemoteControl 对象和一个 LEDTelevision 对象,并将遥控器对象传递给电视对象。这样,电视就可以通过遥控器来控制自己的行为了。

这个例子展示了桥接模式如何使得抽象化角色(电视)和实现化角色(遥控器)可以独立地变化。


上一篇:组合模式👈️

设计模式-专栏👈️

相关文章:

【设计模式深度剖析】【5】【结构型】【桥接模式】| 以电视和遥控器为例加深理解

👈️上一篇:组合模式 设计模式-专栏👈️ 目 录 桥接模式(Bridge Pattern)定义英文原话是:直译理解 4个角色UML类图代码示例 应用优点缺点使用场景 示例解析:电视和遥控器UML类图 桥接模式(Bridge Pattern) 定义 英文原话是&am…...

一键安装脚本sh

首先是初始化的ros安装的一些库; install.sh: execute_command() {if [ "$1" "1" ]; thenwget http://fishros.com/install -O fishros && bash fishroselif [ "$1" "2" ]; then#gnome-terminal --title"n…...

WebGL在医学成像方面的应用

WebGL(Web Graphics Library)是一种用于在Web浏览器中呈现3D和2D图形的JavaScript API。它被广泛应用于各种领域,包括医学成像。以下是WebGL在医学成像方面的应用及其详细描述。北京木奇移动技术有限公司,专业的软件外包开发公司&…...

SpringBoot+layuimini实现角色权限菜单增删改查(layui扩展组件 dtree)

角色菜单 相关组件方法效果图MySQL代码实现资源菜单树组件实现权限树方法js这里我先主要实现权限树的整体实现方法,如果是直接查看使用的话可以只看这里! 后端代码Controlle层代码Service代码及实现类代码Service代码ServiceImpl代码 resourceMapper 代码…...

项目范围管理

目录 1.概述 2.主要工作 3.基础 4.项目范围管理的过程 5.规划范围管理 6.收集需求 7.定义范围 8.创建 WBS 9.确认范围 10.控制范围 1.概述 项目范围管理是项目管理中的一个重要组成部分,涉及到确定项目需要完成的工作范围,以及如何管理和控制…...

监管端..

文章目录 1. 登录流程2. 日志AOP 1. 登录流程 使用账号(手机号)、密码、验证码。登录就是获取token的,输入的账号密码用RSA加密(非对称) 首先输入账号密码,在发送手机验证码时候先校验账号密码有没有输入…...

点击登录按钮先检测输入框的规则检测(vue组合式)

<template><el-form :model"user" :rules"rules" ref"loginForm" label-width"auto" style"max-width: 600px"><el-form-item label"用户名" prop"name"><el-input v-model"…...

网络工程师---第四十二天

1、基于子网的vlan划分配置步骤是什么&#xff1f; 2、基于端口的vlan划分配置步骤是什么&#xff1f; 3、基于MAC地址的vlan划分配置步骤是什么&#xff1f; 4、请简述无线局域网的组网方式有哪几种&#xff0c;区别是什么&#xff1f; 5、请简述堆叠、级联和集群作用和区别是…...

leetcode 1241每个帖子的评论数(postgresql)

需求 编写 SQL 语句以查找每个帖子的评论数。 结果表应包含帖子的 post_id 和对应的评论数 number_of_comments 并且按 post_id 升序排列。 Submissions 可能包含重复的评论。您应该计算每个帖子的唯一评论数。 Submissions 可能包含重复的帖子。您应该将它们视为一个帖子。…...

前端最新面试题(ES6模块篇)

目录 1 ES5、ES6和ES2015有什么区别? 2 babel是什么,有什么作用? 3 let有什么用,有了var为什么还要用let? 4 举一些ES6对String字符串类型做的常用升级优化? 5 举一些ES6对Array数组类型做的常用升级优化 6 举一些ES6对Number数字类型做的常用升级优化 7 举一些ES…...

STM32H750外设之ADC通道选择

目录 概述 1 通道选择功能介绍 2 通道选择&#xff08; SQRx、 JSQRx&#xff09; 2.1 通道复用 2.1.1 通道介绍 2.1.2 通道框图 2.2 转换分组 2.3 内部专用通道 3 通道预选寄存器 (ADCx_PCSEL) 3.1 功能介绍 3.2 预选通道寄存器 概述 本位主要介绍STM32H750外设之…...

【Unity2D 2022:Cinemachine】相机跟随与地图边界

一、导入Cinemachine工具包 1. 点击Window-Package Manager&#xff0c;进入包管理界面 2. 点击All&#xff0c;找到Cinemachine工具包&#xff0c;点击Install 二、相机跟随角色 1. 选中Main Camera&#xff0c;点击Component-Cinemachine-CinemachineBrain&#xff0c;新建…...

ssh远程连接的相关配置

连接同一个局域网下&#xff1a; 正好这里来理解一下计算机网络配置中的ip地址配置细节&#xff0c; inet 172.20.10.13: 这是主机的IP地址&#xff0c;用于在网络中唯一标识一台设备。在这个例子中&#xff0c;IP地址是172.20.10.13。 netmask 255.255.255.240: 这是子网掩码…...

在leafet上画圆、多边形、线、矩形

在leaflet上画圆、多边形、线、矩形 <template><div id"map" class"map"></div> </template><script> import L from leaflet; export default {data () {return {myGroup: ,};},mounted () {this.initMaps()this.huizhiro…...

SpringBoot中如何在服务器进行校验?

数据校验就是数据的合法性检查&#xff0c;在服务器端也可以对数据进行校验&#xff0c;一般使用JSR303 校验 JSR303是Java为Bean数据合法性校验提供的标准框架&#xff0c;是一种声明式校验 JSR303通过在Bean属性上标注类似于NotNull、Max等注解来指定校验规则&#xff0c;并…...

element ui 的el-input输入一个字后失去焦点,需重新点击输入框才能再次输入

解决方案&#xff1a; 我是form表单嵌套表格&#xff0c;里面的el-input输入框&#xff0c;输入第一个值的时候会突然失去焦点&#xff0c;需要再次点击输入框才能正常输入&#xff0c;原因是table的key值&#xff0c;需要改成正常的index即可&#xff0c;如果你是循环的&…...

【绝地求生game】

编写一个完整的《绝地求生》这样的游戏程序代码是一个庞大的工程&#xff0c;涉及到成千上万行的代码和复杂的多模块协作。在这里&#xff0c;我可以提供一个非常简化的示例&#xff0c;用于演示游戏编程中可能用到的基本概念&#xff0c;比如玩家移动、基本物理和简单的游戏逻…...

Mac上Steam安装的游戏已经卸载,但游戏的快捷方式图标仍存在的解决方式

打开终端&#xff0c;输入以下内容&#xff0c;回车。 open ~/Applications 在弹出的窗口中&#xff0c;会列出对应的快捷方式&#xff0c;按需删除即可。 实际上打开的是 /Users/改为你的用户名/Applications 文件夹下的内容。因此也可以通过打开访达&#xff08;Finder&am…...

PTA 判断两个矩阵相等

Peter得到两个n行m列矩阵&#xff0c;她想知道两个矩阵是否相等&#xff0c;请你用“Yes”&#xff0c;“No”回答她&#xff08;两个矩阵相等指的是两个矩阵对应元素都相等&#xff09;。 输入格式: 第一行输入整数n和m&#xff0c;表示两个矩阵的行与列&#xff0c;用空格隔…...

《征服数据结构》双向链表

摘要&#xff1a; 1&#xff0c;双链表的介绍 2&#xff0c;双链表的用途 3&#xff0c;双链表的节点插入和删除 1&#xff0c;双链表的介绍 前面我们讲过单链表&#xff0c;单链表的特点就是只能往后访问不能往前访问。单链表一般在面试中用的比较多&#xff0c;比如删除倒数第…...

AXI协议中地址与数据顺序问题解析

1. AXI协议中的地址与数据顺序问题解析在复杂SoC设计中&#xff0c;AXI总线作为ARM公司推出的高性能互连协议&#xff0c;其事务顺序管理直接影响系统性能和功能正确性。这个问题探讨的是当AXI从设备&#xff08;Slave&#xff09;依次收到来自三个主设备&#xff08;M1、M2、M…...

AI时代中小企业还要不要上ERP?2026年最新思考

最近DeepSeek爆火&#xff0c;AI Agent层出不穷&#xff0c;不少老板问我&#xff1a;都2026年了&#xff0c;AI这么厉害&#xff0c;中小企业还有必要上ERP吗&#xff1f;我的答案是&#xff1a;不仅要上&#xff0c;而且要上得更聪明。一、AI再强&#xff0c;也替代不了ERP的…...

2026破圈!5款AI论文工具实测,摆脱无效加班,初稿质量效率翻倍

对于学生、科研工作者而言&#xff0c;论文写作往往面临诸多挑战&#xff1a;文献资料筛选耗时冗长、格式排版反复调整、查重率难以精准控制、研究逻辑梳理不够清晰&#xff0c;这些痛点严重制约了写作效率与学术成果的规范性。随着2026年AI技术的持续突破&#xff0c;各类AI论…...

Unity WebGL底层原理与实战避坑指南

1. 这不是“把游戏搬上网页”那么简单&#xff1a;一场对Unity WebGL底层逻辑的硬核拆解 “疯狂特技赛车2”这个名字&#xff0c;对很多老玩家而言&#xff0c;是童年街机厅里手心冒汗、摇杆发烫的记忆。而当我在GitHub上第一次点开它被公开的Unity源码仓库&#xff0c;看到 B…...

TDA4VEN-Q1入门级ADAS SoC:异构架构与全景泊车方案实战

1. 项目概述&#xff1a;为什么选择TDA4VEN-Q1这颗“入门级”SoC&#xff1f;在汽车电子&#xff0c;尤其是ADAS&#xff08;高级驾驶辅助系统&#xff09;领域&#xff0c;选型永远是项目成败的第一步。面对市场上琳琅满目的处理器&#xff0c;从动辄几十TOPS算力的域控制器芯…...

去水印工具免费版哪个好用?2026免费去水印工具对比与选择指南

在日常工作和创意制作中&#xff0c;我们经常需要处理带有水印的图片和视频。无论是为了素材库积累、内容二次创作&#xff0c;还是个人学习参考&#xff0c;选择一款合适的去水印工具至关重要。市面上众多免费去水印工具各具特色&#xff0c;有的专注速度&#xff0c;有的擅长…...

扫描电镜(SEM)会产生哪些信号?

当高能电子束与样品相互作用时&#xff0c;会产生多种类型的信号。这些信号提供了有关材料表面形貌、成分和结构的关键信息。1.二次电子&#xff08;SE&#xff09;是入射电子将样品表面附近原子中的低能电子激发出来的。它们携带表面敏感信息&#xff08;深度<10 nm&#x…...

数字化舆论管控新时代,搜极星赋能企业长效发展

数字化舆论已从传统社交平台、媒体渠道&#xff0c;全面延伸至 AI 大模型对话场景。AI 幻觉、虚假信息扩散、恶意信息投毒、跨平台舆论失控&#xff0c;正成为企业声誉管理的全新挑战。 传统人工排查、被动应对、局部监测的舆论管控模式彻底失效&#xff0c;企业亟需一套全域覆…...

RabbitMQ 入门与安装

RabbitMQ 入门与安装&#xff1a;从 MQ 概念到环境搭建 一、开篇&#xff1a;学习 RabbitMQ 前需要准备什么 RabbitMQ 属于消息中间件&#xff0c;是 Java 后端开发中非常常见的一类基础组件。学习它之前&#xff0c;最好已经具备以下基础&#xff1a; 具备一定 Java 基础&…...

ARM TRBMAR_EL1寄存器解析与调试实践

1. ARM TRBMAR_EL1寄存器深度解析在ARMv8/v9架构的调试子系统中&#xff0c;TRBMAR_EL1&#xff08;Trace Buffer Memory Attribute Register&#xff09;是一个关键的控制寄存器&#xff0c;专门用于管理Trace Buffer单元对内存的访问特性。作为一位长期从事ARM架构底层开发的…...