Java设计模式:桥接模式实现灵活组合,超越单一继承的设计之道(十)

在这里插入图片描述

码到三十五 : 个人主页

心中有诗画,指尖舞代码,目光览世界,步履越千山,人间尽值得 !


目录

    • 一、引言
    • 二、什么是桥接设计模式
    • 三、桥接设计模式的核心思想
    • 四、桥接设计模式的角色
    • 五、桥接设计模式的工作流程和实现
      • 实现方式一:使用接口与实现类
      • 实现方式二:使用抽象类与实现类
    • 六、桥接设计模式的优点和适用场景
    • 七、结语

[参见]:

Java设计模式:核心概述(一)

Java设计模式:单例模式之六种实现方式详解(二)

Java设计模式:工厂模式之简单工厂、工厂方法、抽象工厂(三)

Java设计模式:建造者模式之经典与流式的三种实现(四)

Java设计模式:适配器模式的三种形式(五)

Java设计模式:深入装饰器模式的三种写法(六)

Java设计模式:组合模式之透明与安全的两种实现(七)

Java设计模式:代理模式的静态和动态之分(八)

Java设计模式:外观模式之优雅门面(九)

一、引言

在软件设计和开发中,我们经常面临的一个挑战是如何在保持代码灵活性和可扩展性的同时,减少代码之间的耦合度。设计模式就是在这样的背景下应运而生的,它们为开发者提供了一种通用的、经过验证的解决方案来应对常见的设计问题。今天,我们要深入探讨的是Java中的桥接设计模式(Bridge Design Pattern)。

二、什么是桥接设计模式

桥接设计模式,如其名,就像是在两个不同结构或概念之间搭建了一座“桥梁”。在软件设计中,这座“桥梁”连接的是抽象部分和实现部分,使得它们能够独立地变化而互不影响。

具体来说,桥接模式允许你将一个大的或复杂的类(或一组类)拆分为两个独立的层次结构:抽象层次结构和实现层次结构。抽象层次结构定义了操作的接口,而实现层次结构则提供了这些操作的具体实现。这两个层次结构之间通过一个引用(或桥梁)进行连接,从而实现了抽象与实现的解耦。

这种解耦的好处是显而易见的。首先,它提高了代码的灵活性。由于抽象和实现是独立的,你可以在不修改抽象部分的情况下更改或替换实现部分,反之亦然。其次,它增强了代码的可扩展性。你可以独立地扩展抽象部分和实现部分,从而创建出更多的组合和变体。

三、桥接设计模式的核心思想

桥接设计模式的核心思想是“组合优于继承”。这一思想强调通过组合(即对象之间的关联关系)来实现代码的复用和扩展,而不是通过继承(即类之间的层级关系)。

在这里插入图片描述

在面向对象编程中,继承是一种强大的代码复用机制。然而,过度使用继承也会导致一些问题,如代码的可读性下降、维护成本增加以及灵活性降低等。特别是当继承层次过深或过于复杂时,这些问题会变得更加明显。

桥接设计模式通过引入一个抽象层(即桥梁)来分离接口和其具体实现,从而避免了继承带来的这些问题。在这个抽象层中,你可以定义一些抽象的操作或方法,这些方法将委托给具体的实现对象来执行。这样,抽象部分和实现部分就可以通过组合关系进行连接,而不是通过继承关系。

这种组合关系带来了几个好处

  • 首先,它减少了代码之间的耦合度。由于抽象部分和实现部分是独立的,你可以在不修改其他部分的情况下更改或替换其中的一部分。

  • 其次,它提高了代码的灵活性和可扩展性。你可以根据需要动态地组合不同的抽象部分和实现部分,从而创建出满足特定需求的新对象或功能。

  • 最后,它使得代码更加清晰和易于维护。通过将抽象和实现分离,你可以更容易地理解和修改代码的各个部分,从而提高了代码的可读性和可维护性。

四、桥接设计模式的角色

在桥接设计模式中,通常涉及以下几个关键角色:
在这里插入图片描述

  1. Abstraction(抽象):定义一个抽象类,它包含一个对实现对象的引用(通常是接口类型)。这个抽象类将定义一些操作,这些操作将委托给具体的实现对象来执行。

  2. RefinedAbstraction(精化抽象):继承自Abstraction,并为核心抽象增加新的功能。这些功能可能会使用也可能不使用实现对象提供的操作。

  3. Implementor(实现者接口):定义实现对象的接口,该接口声明了实现对象需要提供的具体操作。

  4. ConcreteImplementor(具体实现者):实现Implementor接口,提供具体操作的实现。

五、桥接设计模式的工作流程和实现

在桥接设计模式中,抽象与实现之间的交互通常遵循以下步骤:

    1. 客户端创建一个RefinedAbstraction对象,该对象包含一个指向某个ConcreteImplementor对象的引用。
    1. 客户端通过调用RefinedAbstraction对象的方法来执行某些操作。
    1. 在RefinedAbstraction对象中,这些操作被委托给其包含的ConcreteImplementor对象来实际执行。
    1. 如果需要更换具体的实现,只需要改变RefinedAbstraction对象中引用的ConcreteImplementor对象即可,无需修改RefinedAbstraction对象本身的代码。

实现方式一:使用接口与实现类

  1. 定义实现者接口(Implementor)
// 实现者接口定义了操作的契约
interface Implementor {
    void operationImpl(); // 定义需要实现的操作
}
  1. 定义具体实现者(ConcreteImplementor)
// 具体实现者A实现了实现者接口
class ConcreteImplementorA implements Implementor {
    @Override
    public void operationImpl() {
        System.out.println("具体实现者A的操作实现");
    }
}

// 可以有多个具体实现者,例如B
class ConcreteImplementorB implements Implementor {
    @Override
    public void operationImpl() {
        System.out.println("具体实现者B的操作实现");
    }
}
  1. 定义抽象类(Abstraction)
// 抽象类持有一个对实现者接口的引用
abstract class Abstraction {
    protected Implementor implementor;
    
    public Abstraction(Implementor implementor) {
        this.implementor = implementor;
    }
    
    public void operation() {
        // 调用实现者的操作,可能包括一些抽象类自己的逻辑
        implementor.operationImpl();
    }
}
  1. 定义精化抽象类(RefinedAbstraction)
// 精化抽象类继承自抽象类,并可能增加额外的操作
class RefinedAbstraction extends Abstraction {
    public RefinedAbstraction(Implementor implementor) {
        super(implementor);
    }
    
    public void refinedOperation() {
        // 精化操作,可以调用或不调用实现者的操作
        System.out.println("精化抽象类的额外操作");
        super.operation(); // 可以选择性地调用父类的操作
    }
}
  1. 客户端代码
public class BridgePatternClient {
    public static void main(String[] args) {
        // 创建具体实现者
        Implementor implementorA = new ConcreteImplementorA();
        Implementor implementorB = new ConcreteImplementorB();
        
        // 创建精化抽象类对象,并传入不同的实现者
        Abstraction abstractionA = new RefinedAbstraction(implementorA);
        Abstraction abstractionB = new RefinedAbstraction(implementorB);
        
        // 调用操作
        abstractionA.operation(); // 输出:具体实现者A的操作实现
        ((RefinedAbstraction) abstractionB).refinedOperation(); // 输出:精化抽象类的额外操作 和 具体实现者B的操作实现
    }
}

实现方式二:使用抽象类与实现类

在这种方式中,需要将接口Implementor替换为抽象类,其余结构与方式一类似。这种方式提供了更多的灵活性,允许在实现者之间共享一些状态或行为。

// 将Implementor接口改为抽象类,并添加一些共享的状态或行为...
abstract class Implementor {
    public void sharedOperation() {
        // 共享的操作实现...
    }
    
    public abstract void operationImpl(); // 仍然是抽象方法,需要具体实现者来实现
}

具体实现者将继承这个抽象类,并提供operationImpl方法的实现。其余的代码结构与方式一保持一致。这种方式的优点是可以在不同的实现者之间共享代码,但缺点是可能引入更多的继承层级。选择哪种方式取决于具体的应用场景和需求。

六、桥接设计模式的优点和适用场景

桥接设计模式的优点主要体现在以下几个方面:

  1. 分离抽象与实现:通过将抽象与实现解耦,使得它们可以独立地演化而不相互影响。

  2. 提高灵活性和可扩展性:可以在运行时动态地更换实现,而无需修改客户端代码。

  3. 减少继承带来的层级结构:避免了使用多层继承来组合功能时可能导致的复杂性和僵化性。

桥接设计模式的适用场景包括但不限于:

  • 当一个系统需要在多种平台上运行时,可以使用桥接模式来将系统本身与平台相关的实现细节分离开来。
  • 当一个系统需要支持多种类型的数据库或文件系统等外部资源时,可以使用桥接模式来抽象出资源的通用接口,并通过具体的实现类来适配不同类型的资源。
  • 在需要实现插件化或模块化的系统中,可以使用桥接模式来定义统一的接口标准,并允许第三方开发者提供具体的实现插件或模块。

七、结语

桥接设计模式是一种非常强大且灵活的设计模式,它通过引入一个抽象层来分离接口和其具体实现,从而降低了代码之间的耦合度并提高了代码的灵活性和可扩展性。在实际的项目开发中,我们可以根据具体的需求场景来选择是否应用桥接设计模式以及如何合理地运用它来优化我们的代码结构。



感谢 关注公众号 码到三十五 ,共享更多技术资料。


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何设置win10系统不更新,win10怎么设置系统不更新系统

Win10频繁地更新让很多用户感到困扰,虽然我们都知道,更新系统有利于提高系统的安全性,同时还能获得功能更新以及一些bug修复,但是过于频繁的更新会让人感到疲惫,也有不少用户对此举表示反感。一般情况下,win10系统是默认自动更新的,如何阻止系统自动更新呢?下面,小编跟…

文件夹类型变无?数据恢复有高招!

在日常使用电脑的过程中,我们有时会遇到一种奇怪的现象:原本整齐有序的文件夹突然变成了无类型的状态,即文件夹类型变无。这些文件夹失去了原有的图标和属性,变成了系统无法识别的空白图标,甚至无法打开。这种情况下&a…

甘特图/横道图制作技巧 - 任务组

在甘特图中通过合理的任务分组可以让项目更加清晰,修改也更方便。 列如下面的甘特图一眼不太容易看清楚整体的进度。或者需要把所有的任务整体的延迟或者提前只能这样一个一个的任务调整,就比较麻烦。 通过给任务分组,看这上面整体的进度就…

Redis安装及基本类型详解

目录 一、Redis概念 二、Redis的应用场景 三、Redis的特点 四、redis访问数据为什么快? 五、Ubuntu下安装redis 五、全局命令(针对任意类型value都可使用) 1、keys (1)keys * (2)keys pattern 2、exists 3、…

git Failed to connect to 你的网址 port 8282: Timed out

git Failed to connect to 你的网址 port 8282: Timed out 出现这个问题的原因是:原来的仓库换了网址,原版网址不可用了。 解决方法如下: 方法一:查看git用户配置是否有如下配置 http.proxyhttp://xxx https.proxyhttp://xxx如果…

《梦幻西游》迎来史上最大翻车,老玩家们为何纷纷揭竿而起?

因一次调整,21岁的《梦幻西游》迎来了自己有史以来最大的一波节奏。 玩家在微博上炮轰官方,称:“游戏借着打击工作室牟利的称号,砍副本活动产出,然后自己口袋无限卖”,要求改善游戏现状。 从3月29日起&am…

uniapp 密码框的眼睛

效果展示&#xff1a; uniapp input 官网链接&#xff1a;链接 按照官方文档&#xff0c;uni-icon出不来。 通过自己的方法解决了&#xff0c;解决方案如下&#xff1a; 代码&#xff1a; <uni-forms-item name"password"><inputclass"uni-input&quo…

background背景图参数边渐变CSS中创建背景图像的渐变效果

效果:可以看到灰色边边很难受,希望和背景融为一体 原理: 可以使用线性渐变&#xff08;linear-gradient&#xff09;或径向渐变&#xff08;radial-gradient&#xff09;。以下是一个使用线性渐变作为背景图像 代码: background: linear-gradient(to top, rgba(255,255,255,0)…

【Linux】指令

1. 简单指令 whoami 显示当前登入账号名 ls /home 现在有的用户名 adduser 用户名 新加用户&#xff08;必须在root目录下&#xff09; passwd 用户名 给这个用户设置密码 userdel -r 用户名 删除这个用户 pwd 显示当前所处路径 stat 文件名 / 文件夹名 显示文件状…

学习大数据之JDBC(使用JAVA语句进行SQL操作)(3)

文章目录 DBUtils工具包准备工作DBUtils的介绍QueryRunner空参的QueryRunner的介绍以及使用有参QueryRunner的介绍以及使用 ResultSetHandler结果集BeanHandler<T>BeanListHandler<T>ScalarHanderColumnListHander 事务事务事务_转账分析图实现转账&#xff08;不加…

CTF之GET和POST

学过php都知道就一个简单传参&#xff0c;构造payload:?whatflag得到 flag{3121064b1e9e27280f9f709144222429} 下面是POST那题 使用firefox浏览器的插件Hackbar勾选POST传入whatflag flag{828a91acc006990d74b0cb0c2f62b8d8}

【网站项目】鲜花销售微信小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Dubbo 服务发现

Dubbo 服务发现 1、什么是服务发现 **服务发现&#xff08;Service discovery&#xff09;**是自动检测一个计算机网络内的设备及其提供的服务。 2、Dubbo 与 服务发现 Dubbo 提供的是一种 Client-Based 的服务发现机制&#xff0c;依赖第三方注册中心组件来协调服务发现过…

【算法】两数之和(暴力求解+哈希表)

本题来源---《两数之和》。 题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里…

前端零基础学习web3开发

目录 1 钱包 2 发起交易 3 出块 4 块高 5 矿工 6 Gas费 这一节&#xff0c;我们不说让人神往的比特币&#xff0c;不说自己会不会利用这个虚拟的货币来发财&#xff0c;也不说那些模模糊糊的知识&#xff0c;什么去中心化啦&#xff0c;什么奇妙的加密啦&#xff0c;我们…

云骑士数据恢复怎么授权别的电脑

随着科技的不断发展&#xff0c;数据恢复已经成为了我们生活中不可或缺的一部分。云骑士数据恢复作为一款功能强大的数据恢复软件&#xff0c;受到了广泛的欢迎。但是&#xff0c;有时候我们需要将云骑士数据恢复授权给其他电脑使用&#xff0c;这就需要我们了解相关的操作步骤…

【XCPC笔记】2023 (ICPC) Jiangxi Provincial Contest——ABCHIJKL 做题记录

赛后gym练习及补题&#xff0c;gym链接&#xff1a;2023 (ICPC) Jiangxi Provincial Contest – Official Contest 补题顺序 L [Zhang Fei Threading Needles - Thick with Fine](https://codeforces.com/gym/104385/problem/L)题面解读参考代码 A [Drill Wood to Make Fire](h…

数字电路基础(Digital Circuit Basis )

目录 一、什么是数字电路&#xff1f; &#xff08;Digital Circuit &#xff09; 1.概念 2.分类 3.优点 4.数电与模电的区别 二、数制 (十进制&#xff1a;Decimal) 1.概述 2.进位制 3.基数 4.位权 5.二进制的算术运算 三、编码 (二进制&#xff1a;Binary ) 1.什…

Vue - 你会在同一个元素上使用v-for和v-if吗

难度级别:初级及以上 提问概率:50% 在初学者看来,v-for和v-if同时使用是非常方便的,二者共同使用的常见场景有两种。例如有两个列表,分别用于渲染学生数据和老师数据,然后有两个单选按钮,用于切换当前页面中需要展示学生列表还是老师列…

2024/4/1—力扣—不用加号的加法

代码实现&#xff1a; 思路&#xff1a;位运算&#xff0c;利用了异或和与的特性&#xff0c;异或操作与加操作的区别在于异或操作在二进制状态下两个数同1不进位&#xff0c;只是置为0&#xff0c;其他均相同&#xff0c;那么使用与运算计算进位值&#xff0c;补齐异或操作的缺…