「聊设计模式」之桥接模式(Bridge)

news2024/11/23 2:36:32

🏆本文收录于《聊设计模式》专栏,专门攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎持续关注&&收藏&&订阅!


前言

设计模式是程序员不可或缺的一部分。它们提供了一种通用的方法来解决常见的编程问题,从而提高了代码的可读性和可维护性。在本文中,我们将聊一下设计模式中的“桥接模式”。

摘要

桥接模式是一种结构性设计模式,它允许我们将一个抽象类和它的实现分离开来,从而可以独立地改变它们的实现,而不会影响到客户端代码。

桥接模式

模式概述

  桥接模式是一种结构性设计模式,它将抽象和实现分开,以便它们可以独立地变化。它通过使用组合来代替继承来实现这个目标。

  在桥接模式中,有两个类层次结构:抽象类和实现类。抽象类定义了一个接口,它包含了一些基本的操作方法。实现类实现了这些操作方法,并将它们映射到具体的实现上。通过这种方式,客户端代码和具体的实现之间就解耦了。

模式结构

桥接模式的结构包括四个主要部分:

  1. 抽象化(Abstraction):定义抽象类,并包含一个指向实现化对象的引用,抽象类的接口将调用实现化类中的方法。

  2. 实现化(Implementor):定义实现化接口,具体实现化类将实现此接口。

  3. 具体抽象化(Refined Abstraction):扩展抽象化接口以支持更多功能,实现类将实现这些方法。

  4. 具体实现化(Concrete Implementor):实现实现化接口的类,并提供具体实现。

其结构图如图所示:

在这里插入图片描述

模式优势

  使用桥接模式的主要优势在于它能够将抽象和实现分离开来,并将它们独立地变化。这意味着,如果你需要改变实现方式,你只需要改变实现类,而不需要改变客户端代码。

  此外,使用桥接模式可以提高代码的可读性和可维护性。因为它将功能分解成小的模块,而不是大而复杂的类。这使得代码更容易理解、调试和修改。

模式缺点

  桥接模式的主要缺点在于它增加了代码的复杂性。因为它需要将抽象和实现分开,所以需要增加更多的类和层次结构。这可能会使代码难以理解、调试和维护。

适用场景

桥接模式适用于以下场景:

  • 当你需要将一个抽象类和它的实现分开时。
  • 当你需要支持多种平台或多种操作系统时。
  • 当你需要改变一个类的实现方式时,而不想影响到客户端代码。

模式实现

下面通过一个例子来说明桥接模式的实现过程。

假设我们要设计一个图形库,其中包含两个基本功能:绘制不同种类的图形和使用不同的颜色进行填充。我们可以使用桥接模式来实现这个图形库,其中抽象部分为Shape,实现部分为Color,桥接接口为DrawAPI。

先看一下Shape的抽象类:

package com.example.javaDesignPattern.bridge;

/**
 * 抽象类
 *
 * @author bug菌
 * @version 1.0
 * @date 2023/9/19 11:19
 */
public abstract class Shape {
    protected DrawAPI drawAPI;

    public Shape(DrawAPI drawAPI) {
        this.drawAPI = drawAPI;
    }

    public abstract void draw();
}

可以看到,Shape包含了一个对DrawAPI的引用,并且定义了一个抽象的draw方法,用于绘制图形。

再看一下DrawAPI的接口:

package com.example.javaDesignPattern.bridge;

/**
 * 抽象接口
 *
 * @author bug菌
 * @version 1.0
 * @date 2023/9/19 11:19
 */
public interface DrawAPI {
    public void draw();
}

DrawAPI定义了一个draw方法,Shape的实现类将通过它来使用不同的颜色进行填充。

然后是Shape的实现类:Circle、Rectangle和Triangle。

package com.example.javaDesignPattern.bridge;

/**
 * Shape的实现类
 * 
 * @author bug菌
 * @version 1.0
 * @date 2023/9/19 11:20
 */
public class Circle extends Shape {
    private int x, y, radius;

    public Circle(int x, int y, int radius, DrawAPI drawAPI) {
        super(drawAPI);
        this.x = x;
        this.y = y;
        this.radius = radius;
    }

    public void draw() {
        drawAPI.draw();
    }
}
package com.example.javaDesignPattern.bridge;

/**
 * Shape的实现类
 * 
 * @author bug菌
 * @version 1.0
 * @date 2023/9/19 11:21
 */
public class Rectangle extends Shape {
    private int x, y, width, height;

    public Rectangle(int x, int y, int width, int height, DrawAPI drawAPI) {
        super(drawAPI);
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    public void draw() {
        drawAPI.draw();
    }
}
package com.example.javaDesignPattern.bridge;

/**
 * Shape的实现类
 *
 * @author bug菌
 * @version 1.0
 * @date 2023/9/19 11:22
 */
public class Triangle extends Shape {
    private int x1, y1, x2, y2, x3, y3;

    public Triangle(int x1, int y1, int x2, int y2, int x3, int y3, DrawAPI drawAPI) {
        super(drawAPI);
        this.x1 = x1;
        this.y1 = y1;
        this.x2 = x2;
        this.y2 = y2;
        this.x3 = x3;
        this.y3 = y3;
    }

    public void draw() {
        drawAPI.draw();
    }
}

可以看到,它们都继承了Shape,并实现了draw方法。在构造方法中,将DrawAPI对象传递给了Shape的构造方法,从而实现了抽象部分和实现部分的连接。

最后是Color的实现类:Red、Green和Blue。

package com.example.javaDesignPattern.bridge;

/**
 * Color的实现类
 *
 * @author bug菌
 * @version 1.0
 * @date 2023/9/19 11:24
 */
public class Red implements DrawAPI {
    public void draw() {
        System.out.println("fill with red");
    }
}
public class Green implements DrawAPI {
    public void draw() {
        System.out.println("fill with green");
    }
}
public class Blue implements DrawAPI {
    public void draw() {
        System.out.println("fill with blue");
    }
}

它们都实现了DrawAPI接口,并提供了具体的draw方法,用于绘制不同的颜色。

最后我们可以编写一个测试用例来验证桥接模式的实现:

package com.example.javaDesignPattern.bridge;

/**
 * @author bug菌
 * @version 1.0
 * @date 2023/9/19 11:15
 */
public class Client {

    public static void main(String[] args) {
        Shape circle = new Circle(100,100, 10, new Red());
        circle.draw();

        Shape rectangle = new Rectangle(50, 50, 20, 30, new Green());
        rectangle.draw();

        Shape triangle = new Triangle(10, 20, 30, 40, 50, 60, new Blue());
        triangle.draw();
    }
}

执行结果如下:

在这里插入图片描述

代码分析:
  如上代码是一个简单的示例程序,其中定义了一个Client类。在main方法中,创建了三个形状对象circle、rectangle和triangle,并使用draw方法绘制了它们。

这三个形状对象分别是:

  • Circle:圆形,构造函数中参数依次为圆心位置x、y坐标、半径和颜色对象。
  • Rectangle:矩形,构造函数中参数依次为左上角位置x、y坐标、宽度、高度和颜色对象。
  • Triangle:三角形,构造函数中参数依次为三个顶点的x、y坐标和颜色对象。

  在这里,颜色对象是使用了简单工厂模式创建的,包括Red、Green和Blue。

小结

  在本文中,我们介绍了桥接模式,它是一种结构性设计模式,用于将一个抽象类和它的实现分开。我们看了一个简单的例子来理解这个模式,然后讨论了它的优点、缺点和适用场景。最后,我们提供了一些代码和测试用例来帮助你在实际中应用这个模式。

附录源码

  如上涉及代码均已上传同步在GitHub,提供给同学们参考性学习。

总结

桥接模式是一种非常有用的设计模式,可以将抽象和实现分开,从而提高代码的可读性和可维护性。它可以帮助我们实现更灵活、更可扩展的代码,适用于需要支持多种平台或多种操作系统的情况。如果您正在开发一个需要支持多种平台的应用程序,或者需要改变一个类的实现方式,而不想影响到客户端代码,那么您应该考虑使用桥接模式。

☀️建议/推荐你


  如果想系统性的全面学习设计模式,建议小伙伴们直接毫无顾忌的关注这个专栏《聊设计模式》,无论你是想提升自己的编程技术,还是渴望更好地理解代码背后的设计思想,本专栏都会为你提供实用的知识和启发,帮助你更好地解决日常开发中的挑战,将代码变得更加优雅、灵活和可维护!

📣关于我


我是bug菌,CSDN | 掘金 | infoQ | 51CTO 等社区博客专家,历届博客之星Top30,掘金年度人气作者Top40,51CTO年度博主Top12,华为云 | 阿里云| 腾讯云等社区优质创作者,全网粉丝合计15w+ ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板等海量资料。

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

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

相关文章

华为数通方向HCIP-DataCom H12-831题库(单选题:61-80)

第61题 R3与R4的IS-IS Leve1-1邻居没有建立,根据本图的信息可能的原因是? A、R3与R4的互连接口circuit-type不四配 B、R3与R4的区域号不同 C、R3与R4的IS-Leve1不匹配 D、R3与R1的IIH认证失败 答案:B 解析: 直接看图中的非0数字就能得出答案。 Display isis error 是查看…

如何开心的在iOS上玩NDS游戏

如何开心的在iOS上玩NDS游戏 先说结论,有原生方案和web方案2种。 Web 方案 其实现在的 webassembly 技术已经非常成熟了,我们可以通过编译 C 语言的模拟器代码,然后在浏览器上运行。 这样就可以实现一个在线的模拟器了,而且不…

内网穿透的应用-Cloudreve搭建云盘系统,并实现随时访问

文章目录 1、前言2、本地网站搭建2.1 环境使用2.2 支持组件选择2.3 网页安装2.4 测试和使用2.5 问题解决 3、本地网页发布3.1 cpolar云端设置3.2 cpolar本地设置 4、公网访问测试5、结语 1、前言 自云存储概念兴起已经有段时间了,各互联网大厂也纷纷加入战局&#…

mysql表的导出和导入

表的导出 mysql 默认对导出的目录有权限限制,也就是说使用命令进行导出的时候,需要指定目录进行操作 show global variables like ‘%secure%’; secure_file_priv 值情况分析: 如果设置为empty,表示不限制文件生成的位置&#x…

MySQL:获取Auto_increment失败问题记录

项目场景: 人员权限设置,定义了一张存储自增id的表sys_id_sequence(A表) /*A表定义*/ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS 0;-- ---------------------------- -- Table structure for sys_id_sequence -- -----------…

PyTorch深度学习实战(16)——面部关键点检测

PyTorch深度学习实战(16)——面部关键点检测 0. 前言1. 关键点检测1.1 关键点检测模型分析1.2 数据集分析 2. 面部关键点检测3. 2D 和 3D 面部关键点检测小结系列链接 0. 前言 我们已经学习了如何解决二分类(猫狗分类)和多分类( fashionMNIST )问题。本…

Python(八十七)函数的定义与调用

❤️ 专栏简介:本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中,我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 :本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…

ffmpeg抠图

1.不用png,用AVFrame 2.合流 3.图片抠图透明 (1.)mp4扣yuv图,(2)用1. (3)用抠图算法函数对yuv进行处理 ffmpeg -y -i TJTV.png -vf colorkey0x0000FF:0.5:0.0 -c:v png t.png0x0000FF:六位每两位分别表示红绿蓝,因此它是对…

如何提高技术领导力?与你分享 5 个心得

技术领导力于很多人而言都是谜一般的存在。有观点认为,实战经验丰富的资深开发最终只有成为技术管理者才能继续成长。从某些方面来看,这可能是对的,但考虑到公司结构和规章制度等,想要完成从「个人贡献者」到「技术管理者」的跨越…

mysql自动删除过期的binlog

一、binlog_expire_logs_seconds 配置项 mysql 8.0使用配置项 binlog_expire_logs_seconds 设置binlog过期时间,单位为秒。 mysql旧版本使用配置项 expire_logs_days 设置binlog过期时间,单位为天,不方便测试。 在 8.0 使用 expire_logs_d…

CH2--x86系统架构概览

2.1 OVERVIEW OF THE SYSTEM-LEVEL ARCHITECTURE IA-32 与 IA32-e 模式 图中的实线箭头表示线性地址,虚线表示段选择器,虚线箭头表示物理地址 2.1.1 Global and Local Descriptor Tables 全局描述符表 (GDT) GDT是一个全局的段描述符表,它存储…

「聊设计模式」之适配器模式(Adapter)

🏆本文收录于《聊设计模式》专栏,专门攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎持续关注&&收藏&&订阅! 前言 在软件开发中,经常会涉及到现有系统的改造和升…

微信小程序云开发手搓微标提示,逻辑思路记录及代码实现

目录 写前小叙 功能需求背景 首页js的逻辑思路第一部分 发布公告js逻辑 首页js显示“新”公告思路实现 首页js关闭“新”公告思路实现 管理员“已阅读”js逻辑 首页js显示“新”邮件思路实现 首页js关闭“新”邮件思路实现 写前小叙 今儿凌晨,我又是一个人…

【Python】福利彩票复式模拟选号程序

【效果】 【注意】 逻辑是用Random模拟10000次复试彩票选号,然后给出最大可能性一组。但是模拟终究是模拟,和现实彩票结果没有任何联系,下载下来玩就是了,没人能保证模拟出中奖号码,不要投机,不要投机! 【修改】 代码很简单,如果想改成不是复式的,自行修改即可。 如…

linux学习实操计划0103-安装软件

本系列内容全部给基于Ubuntu操作系统。 系统版本:#32~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Aug 18 10:40:13 UTC 1 安装deb格式软件 Debian包是Unixar的标准归档,将包文件信息以及包内容,经过gzip和tar打包而成。 处理这些包的经典程序是…

【IntelliJ IDEA】切换jdk版本配置

需求描述 idea 2020.3.1 原来idea使用的是jdk8的版本,想换成jdk7的版本,该怎么配置呢?配置哪些地方呢? 解决方法 local1 先在Project Structure中,添加上刚安装的jdk7(它的安装目录) local…

数据结构——线性表之顺序表

目录 一.线性表 二.顺序表实现 2.1 概念及结构 2.2 动态顺序表 2.2.1 初始化与销毁函数 2.2.2 打印函数 2.2.3 尾插函数 2.2.4 尾删函数 2.2.5 扩容函数 2.2.6 头插函数 2.2.7 头删函数 2.2.8 任意位置插入函数 2.2.9 查找函数 2.2.10 任意位置删除函数 2.2.11 修…

2023年9月中国数据库排行榜:阿里叱咤云端登榜眼,华为中兴厚积薄发显峥嵘

鸿鹄展翅凌云志,骏马扬蹄踏雪心。 2023年9月的 墨天轮中国数据库流行度排行 火热出炉,本月共有287个数据库参与排名。本月排行榜前十中,OceanBase 连续10个月稳居榜首,头部产品得分差距日益缩小,阿里华为两大云厂商持续…

react使用内联css样式的注意点

react使用内联css样式: 就是直接在元素标签的style属性中写css样式,但是这里有三个注意点: 1. style等号后面必须接双大括号也就是 style{{ xx: xx }} 这样 2. css的属性必须写成驼峰型,不能有中横线,比如marginRight, 而不能说margin-righ…

Axure原型设计累加器计时器设计效果(职业院校技能大赛物联网技术应用项目原型设计题目)

目录 前言 一、本题实现效果 二、操作步骤 1.新建文件 2.界面设计 2.1文本框 2.2 按钮 2.3设计界面完成 3.交互 3.1启动交互设置 3.2 分别设置三个属性 3.2.1 设置值为“0” 3.2.2 文字于文本框 3.2.3 获取焦点时 3.3 停止按钮的交互动作 3.3.1 设置变量值 3.4 重…