设计模式之桥接模式:抽象与实现之间的分离艺术

news2024/12/19 5:39:42

在这里插入图片描述

~犬📰余~

“我欲贱而贵,愚而智,贫而富,可乎?
曰:其唯学乎”

桥接模式概述与角色组成

想象一下你家里的电视遥控器,无论是索尼还是三星的电视机,遥控器的按键功能都差不多:有开关按钮、音量调节、频道切换等。遥控器本身的功能(抽象)和具体品牌电视的实现(实现)是分离的,这就是桥接模式的一个生动写照。
桥接模式的核心思想是将抽象部分与实现部分分离,让它们都可以独立变化。这就好比建造一座桥,把两个独立的部分连接起来。在我们的电视机例子中,遥控器就是连接用户操作和电视机的"桥梁"。
在这里插入图片描述
如上图所示,桥接模式由四个核心角色组成:

  • 抽象类(Abstraction):定义抽象类的接口,它包含一个对实现类接口的引用。就像遥控器的抽象类,定义了基本的控制功能,并持有对具体电视机的引用。
  • 扩展抽象类(RefinedAbstraction):扩展抽象类,加入更多的功能特性。比如在基础遥控器的基础上,添加了更多高级功能的智能遥控器。
  • 实现类接口(Implementor):定义实现类的接口,供抽象类调用。就像所有品牌电视机都应该遵循的标准接口,定义了开关机、调节音量等基本功能。
  • 具体实现类(ConcreteImplementor):实现实现类接口的具体类。例如索尼电视机、三星电视机等具体品牌的电视机实现。

这种设计的妙处在于:如果我们要添加一种新的遥控器类型(比如带语音控制的遥控器),只需要扩展抽象类;如果要支持一个新品牌的电视机,只需要添加具体实现类。两个维度的变化互不影响,大大提高了系统的灵活性和可扩展性。

桥接模式案例实现

让我们通过遥控器控制电视机的完整示例,来深入理解桥接模式的实现。
在这里插入图片描述
首先,我们定义电视机的接口:

public interface TV {
    void on();
    void off();
    void tuneChannel(int channel);
}

然后实现具体品牌的电视机:

public class SonyTV implements TV {
    @Override
    public void on() {
        System.out.println("索尼电视机启动");
    }
    
    @Override
    public void off() {
        System.out.println("索尼电视机关闭");
    }
    
    @Override
    public void tuneChannel(int channel) {
        System.out.println("索尼电视切换到" + channel + "频道");
    }
}

public class SamsungTV implements TV {
    @Override
    public void on() {
        System.out.println("三星电视机启动");
    }
    
    @Override
    public void off() {
        System.out.println("三星电视机关闭");
    }
    
    @Override
    public void tuneChannel(int channel) {
        System.out.println("三星电视切换到" + channel + "频道");
    }
}

接下来定义遥控器的抽象类:

public abstract class RemoteControl {
    protected TV tv;
    
    public RemoteControl(TV tv) {
        this.tv = tv;
    }
    
    public abstract void turnOn();
    public abstract void turnOff();
}

实现具体的遥控器类:

public class BasicRemote extends RemoteControl {
    public BasicRemote(TV tv) {
        super(tv);
    }
    
    @Override
    public void turnOn() {
        System.out.println("基础遥控器:打开电视");
        tv.on();
    }
    
    @Override
    public void turnOff() {
        System.out.println("基础遥控器:关闭电视");
        tv.off();
    }
}

public class AdvancedRemote extends RemoteControl {
    public AdvancedRemote(TV tv) {
        super(tv);
    }
    
    @Override
    public void turnOn() {
        System.out.println("高级遥控器:打开电视");
        tv.on();
    }
    
    @Override
    public void turnOff() {
        System.out.println("高级遥控器:关闭电视");
        tv.off();
    }
    
    // 高级遥控器特有的功能
    public void setChannel(int channel) {
        System.out.println("高级遥控器:切换频道");
        tv.tuneChannel(channel);
    }
}

下面通过一个具体的客户端代码来演示如何使用这个遥控器-电视机系统:

public class Client {
    public static void main(String[] args) {
        // 创建不同品牌的电视
        TV sonyTV = new SonyTV();
        TV samsungTV = new SamsungTV();

        // 创建不同类型的遥控器
        RemoteControl basicRemote = new BasicRemote(sonyTV);
        AdvancedRemote advancedRemote = new AdvancedRemote(samsungTV);

        // 使用基础遥控器操作索尼电视
        System.out.println("使用基础遥控器操作索尼电视:");
        basicRemote.turnOn();
        basicRemote.turnOff();

        System.out.println("使用高级遥控器操作三星电视:");
        advancedRemote.turnOn();
        advancedRemote.setChannel(5);
        advancedRemote.turnOff();
    }
}

运行结果如下:
在这里插入图片描述
让我们通过下面的时序图来详细说明对象之间的交互过程:
在这里插入图片描述
从时序图中我们可以清晰地看到,当客户端调用遥控器的turnOn()方法时,遥控器会将请求转发给具体的电视机实现类。这种方式让遥控器和电视机之间形成了一个优雅的"桥接",它们可以独立变化而互不影响。

桥接模式的优缺点

优点

  • 很好地实现了抽象和实现的分离。就像我们的例子中,遥控器的功能和电视机的实现是完全分离的,这让我们能够独立地扩展任意一边而不会影响另一边。你可以添加一个带有语音控制功能的遥控器,而不需要修改任何电视机的代码。
  • 提高了系统的可扩展性。当系统需要添加新的实现时,只需要增加新的类,而不需要修改现有的代码。比如要支持新品牌的电视机,只需要实现TV接口即可,不需要修改任何遥控器的代码。
  • 对客户端来说很友好。客户端代码只需要知道抽象部分的接口,而不需要了解具体实现的细节。在我们的例子中,使用遥控器的人只需要知道按键的功能,而不需要关心不同品牌电视机的具体实现差异。

缺点

  • 增加了系统的复杂度。为了实现抽象和实现的分离,我们需要额外的接口和类。对于简单的系统来说,使用桥接模式可能会显得有点过度设计。
  • 要求正确识别系统中的两个独立变化的维度。如果对系统的理解不够深入,可能会导致对抽象和实现的划分不当,反而增加系统的维护难度。

桥接模式的适用场景

  • 当一个系统需要在抽象和实现之间具有灵活性时。例如,我们的遥控器和电视机的例子,两者之间的组合是动态的,任何遥控器都可以操控任何品牌的电视机。
  • 当系统中有两个或多个独立变化的维度时。比如除了遥控器和电视机的例子,类似的场景还有:形状和颜色(可以有不同形状和不同颜色的组合)、平台和视图(可以在不同平台上实现不同的视图)等。
  • 当需要跨平台或跨数据库时。桥接模式可以让具体的平台实现和业务逻辑分离,使得系统可以轻松地支持新的平台。
  • 当需要在运行时切换不同的实现时。由于抽象和实现是分离的,我们可以在运行时动态地改变实现,而不会影响到使用抽象接口的代码。

总结

桥接模式通过将抽象部分与实现部分分离,实现了两个维度上的独立扩展。就像遥控器和电视机的例子展示的那样,它让我们能够在不修改现有代码的情况下,轻松地添加新的遥控器类型或支持新品牌的电视机。
在实际应用中,使用桥接模式时需要注意以下几点:首先,要准确识别系统中独立变化的维度;其次,要合理划分抽象和实现的界限;最后,要避免过度设计,对于简单的系统,使用过于复杂的模式反而会增加开发和维护的成本。
桥接模式的精髓在于"分离抽象与实现",这种分离让系统更加灵活,更容易扩展和维护。当你遇到类似的场景时,不妨考虑使用桥接模式来优化你的设计。
在这里插入图片描述

关注犬余,共同进步

技术从此不孤单

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【从零开始入门unity游戏开发之——C#篇17】C#面向对象的封装——类(Class)和对象、成员变量和访问修饰符、成员方法

文章目录 一、类和对象1、什么是类和对象?2、例子说明2.1 例子1:(1) **类的定义:**(2) **创建对象:**(3) **类和对象的关系:** 2.2 例子2:**类的比喻:****对象的比喻:**代码实例&…

在Ubuntu 22.04 LTS中使用PyTorch深度学习框架并调用多GPU时遇到indexSelectLargeIndex相关的断言失败【笔记】

在Ubuntu 22.04 LTS系统中,已安装配置好CUDA 12.4、cuDNN 9.1.1以及PyTorch环境 export CUDA_VISIBLE_DEVICES0,1,2,3,4,5,6,7 在PyTorch深度学习框架训练调用多GPU时,提示 indexSelectLargeIndex: block: [x, 0, 0], thread: [x, 0, 0] Assertion src…

FutureCompletableFuture实战

1. Callable&Future&FutureTask介绍 直接继承Thread或者实现Runnable接口都可以创建线程,但是这两种方法都有一个问题就是:没有返回值,也就是不能获取执行完的结果。因此java1.5就提供了Callable接口来实现这一场景,而Fu…

[论文阅读笔记]-PalmTree: 学习一个用于指令嵌入的汇编语言模型

深度学习已在众多二进制分析任务中展示了其优势,包括函数边界检测、二进制代码搜索、函数原型推理、值集分析等。现有方案忽略了复杂的指令内结构,主要依赖于控制流,其中上下文信息是嘈杂的,并且可能受到编译器优化的影响。为了解…

CH582F BLE5.3 蓝牙核心板开发板 60MHz RAM:32KB ROM:448KB

CH582F BLE5.3 蓝牙核心板开发板 60MHz RAM:32KB ROM:448KB 是一款基于南京沁恒(WCH)推出的高性能、低功耗无线通信芯片CH582F的开发板。以下是该开发板的功能和参数详细介绍: 主要特性 双模蓝牙支持: 支持蓝牙5.0标准&#xff0…

数字IC后端设计实现篇之TSMC 12nm TCD cell(Dummy TCD Cell)应该怎么加?

TSMC 12nm A72项目我们需要按照foundary的要求提前在floorplan阶段加好TCD Cell。这个cell是用来做工艺校准的。这个dummy TCD Cell也可以等后续Calibre 插dummy自动插。但咱们项目要求提前在floorplan阶段就先预先规划好位置。 TSCM12nm 1P9M的metal stack结构图如下图所示。…

《网络对抗技术》Exp9 Web安全基础

实验目标 理解常用网络攻击技术的基本原理。 实验内容 Webgoat实践下相关实验。 实验环境 macOS下Parallels Desktop虚拟机中(网络源均设置为共享网络模式): Kali Linux - 64bit(攻击机,IP为10.211.55.10)…

Chrome 132 版本开发者工具(DevTools)更新内容

Chrome 132 版本开发者工具(DevTools)更新内容 一、使用 Gemini 调试 Network、Source 和 Performance Chrome 131 可以使用 Gemini 调试 CSS,现在可以调试更多模块了 与元素面板中的右键菜单类似,要打开 AI 辅助面板并开始与 …

消息系统之 Kafka

什么是消息系统 消息系统是专用的中间件,负责将数据从一个应用传递到另外一个应用。使应用只需关注于数据,无需关注数据在两个或多个应用间是如何传递的。 消息系统一般基于可靠的消息队列来实现,使用点对点模式或发布订阅模式。数据实时在…

Intel-ECI之Codesys PLC + Ethercat 远端IO + Codesys IDE编程

目录 一、 准备工作 二、安装Codesys 软件 PLC 三、 使用Codesys IDE 编程测试 CODESYS* 是领先的独立于制造商的 IEC 61131-3 自动化软件,适用于工程控制系统。它用于 Intel Edge Controls for Industrial(Intel ECI 或 ECI),…

[2015~2024]SmartMediaKit音视频直播技术演进之路

技术背景 2015年,因应急指挥项目需求,我们实现了RTMP推送音视频采集推送(采集摄像头和麦克风数据)模块,在我们做好了RTMP推送模块后,苦于没有一个满足我们毫秒级延迟诉求的RTMP播放器,于是第一…

Ubuntu24.04 安装 visual studio code

# 导入软件包密钥 wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg sudo install -D -o root -g root -m 644 packages.microsoft.gpg /etc/apt/keyrings/packages.microsoft.gpg# 添加官方库 echo "deb [arch…

docker 搭建自动唤醒UpSnap工具

1、拉取阿里UpSnap镜像 docker pull crpi-k5k93ldwfc7o75ip.cn-hangzhou.personal.cr.aliyuncs.com/upsnap/upsnap:4 2、创建docker-compose.yml文件,进行配置: version: "3" services:upsnap:container_name: upsnapimage: crpi-k5k93ldwf…

已解决:elasticsearch创建索引失败

报错信息 具体报错: org.elasticsearch.ElasticsearchStatusException: Elasticsearch exception [typeillegal_argument_exception, reasonunknown setting [index.mappings.properties.category.analyzer] please check that any required plugins are installed…

PHPstudy中的数据库启动不了

法一 netstat -ano |findstr "3306" 查看占用该端口的进程号 taskkill /f /pid 6720 杀死进程 法二 sc delete mysql

计算机视觉中的特征提取算法

摘要: 本文聚焦于计算机视觉中的特征提取算法,深入探讨尺度不变特征变换(SIFT)算法。详细阐述 SIFT 算法的原理,包括尺度空间构建、关键点检测、方向分配与特征描述子生成等核心步骤。通过 C#、Python 和 C 三种编程语…

Linux USB开发整理和随笔

目录 1 概述 2 硬件原理基础 2.1 USB发展 2.2 USB的拓扑 2.3 硬件接口 2.4 USB总线协议 2.4.1 通信过程 2.4.2 概念关系 2.4.3 管道PIPE 2.4.4 传输 2.4.5 事务 2.4.6 包结构与类型 2.4.6.1 令牌包 2.4.6.2 数据包 2.4.6.3 握手包 2.5 描述符 2.5.1 设备描述符…

从0开始深入理解并发、线程与登台通知机制

1、从0开始深入理解并发、线程与等待通知机制 为什么开发中需要并发编程? 从阿里、美团的岗位JD其实就能看出来,并发编程和性能优化是密切相关的,使用并发编程可以做到: (1)加快响应用户的时间 比如我们经常用的迅雷下载,都喜欢…

简易记事本项目(基于Vue 3 + Element Plus + SSM 个人事件管理系统)

项目简介 点滴365是一个基于 Vue 3 Element Plus SSM 开发的个人事件管理系统,旨在帮助用户高效管理 个人日程 和 待办事项。系统支持日记撰写、待办事项管理、数据统计分析、图片上传、定时提醒、实时天气等功能,让用户可以更好地记录生活点滴、规划工作任务。 核心技术栈…

IIS服务器部署C# WebApi程序,客户端PUT,DELETE请求无法执行

这两天在自己Windows10电脑上搭建IIS服务器,把自己写的WebApi代码部署上做个本地服务器,结果客户端的PUT和DELETE请求无法执行,GET、POST这些都正常,研究后发现要删除IIS中的“模块”中的"webdavmodule"才能解决。