桥接模式学习

目录

  • 背景
  • 过程
  • 总结

背景

现在要解决源码阶段的继承关系,无法在运行时改变从父类继承的实现。这里用的是手机品牌还有手机中的app,这种问题如何进行解决呢。这就要引入一个模式:桥接模式

过程

1、原则:合成/复用原则 :尽量使用合成/聚合原则,不要使用类继承。
2、定义:将抽象部分和它的实现分离,使他们都可以独立变化。(不是说抽象类和实现类分离,实现指的是抽象类和它的派生类用来实现自己的对象。)

3、例子:

如手机品牌和手机app的关系,他们可以是继承关系,也可以是关联关系。

如果是继承关系的话,是对象的继承关系在编译的时候定义好了,无法在运行时改变从父类继承的实现。子类的视线和它的父类有很紧密的依赖关系,父类实现中的任何变化必然会导致子类发生变化。于是出现了这种聚合关系。

在这里插入图片描述

  1. Abstraction抽象类
public abstract class Abstraction {

    private Implementor imp;

    //约束子类必须实现该构造函数
    public Abstraction(Implementor imp) {
        this.imp = imp;
    }
    
    public Implementor getImp() {
        return imp;
    }

    //自身的行为和属性
    public void request() {
        this.imp.doSomething();
    }
    
}

  1. Implementor抽象类
public abstract class Implementor {

    public abstract void doSomething();
    public abstract void doAnything();
    
}

  1. ConcreteImplementor
public class ConcreteImplementorA extends Implementor {

    
    public void doSomething() {
        System.out.println("具体实现A的doSomething执行");
    }
    
    
    public void doAnything() {
        System.out.println("具体实现A的doAnything执行");
    }
}

  1. RefinedAbstraction
public class RefinedAbstraction extends Abstraction {

    //覆写构造函数
    public RefinedAbstraction(Implementor imp) {
        super(imp);
    }
    
    //修正父类行为
    
    public void request() {
        super.request();
        super.getImp().doAnything();
    }
    
}

  1. Client客户端
public class Client {

    public static void main(String[] args) {
        Implementor imp = new ConcreteImplementorA();
        Abstraction abs = new RefinedAbstraction(imp);
        abs.request();
    }
    
}

二、桥接模式的应用
1. 何时使用

系统可能有多个角度分类,每一种角度都可能变化时

2. 方法

把这种角度分类分离出来,让它们单独变化,减少它们之间的耦合(合成/聚合复用原则)

3. 优点

抽象和实现分离。桥梁模式完全是为了解决继承的缺点而提出的设计模式
优秀的扩展能力
实现细节对客户透明。客户不用关心细节的实现,它已经由抽象层通过聚合关系完成了封装

4. 缺点

会增加系统的理解与设计难度。由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程

5. 使用场景

不希望或不适用使用继承的场景
接口或抽象类不稳定的场景
重用性要求较高的场景

6. 应用实例

开关。我们可以看到的开关是抽象的,不用管里面具体怎么实现
手机品牌与手机软件。两者间有一条聚合线,一个手机品牌可以有多个手机软件

7. 注意事项

不要一涉及继承就考虑该模式,尽可能把变化的因素封装到最细、最小的逻辑单元中,避免风险扩散
当发现类的继承有n层时,可以考虑使用该模式.

三、桥接模式的实现
下面我们举一个例子,就拿上面说的手机品牌与手机软件为例,我们可以让手机既可以按照手机品牌来分类,也可以按手机软件来分类。由于实现的方式有多种,桥接模式的核心意图就是把这些实现独立出来,让它们各自地变化,这就使得没中实现的变化不会影响其他实现,从而达到应对变化的目的。
在这里插入图片描述

  1. 手机品牌抽象类
public abstract class HandsetBrand {

    protected HandsetSoft soft;
    
    //设置手机软件
    public void setHandsetSoft(HandsetSoft soft) {
        this.soft = soft;
    }
    
    //运行
    public abstract void run();
    
}

  1. 手机软件抽象类
public abstract class HandsetSoft {

    public abstract void run();
    
}

  1. 各类手机品牌
public class HandsetBrandA extends HandsetBrand {

    
    public void run() {
        soft.run();
    }
    
}

  1. 各类手机软件
public class HandsetGame extends HandsetSoft {

    
    public void run() {
        System.out.println("运行手机游戏");
    }

}

5. Client客户端
public class Client {

    public static void main(String[] args) {
        HandsetBrand ab;
        
        //使用A品牌手机
        ab = new HandsetBrandA();
        System.out.println("A品牌手机:");
        
        ab.setHandsetSoft(new HandsetGame());
        ab.run();
        
        ab.setHandsetSoft(new HandsetAddressList());
        ab.run();
        
        //分隔符
        System.out.println("---------------");
        
        //使用B品牌手机
        ab = new HandsetBrandB();
        System.out.println("B品牌手机:");
        
        ab.setHandsetSoft(new HandsetGame());
        ab.run();
        
        ab.setHandsetSoft(new HandsetAddressList());
        ab.run();
    }
    
}

总结

这个桥接模式最深刻的一个点是:将源码定义好的关系修改为运行时在客户端中指定关系。解开源码定义好的类之间的耦合,变成运行的时候才让类之间耦合起来。

这样我现在如果想要增加一个功能,比如音乐播放器,那么只有增加这个类就可以了,不会影响到其他任何类,类的个数增加也只是一个;如果是要增加S品牌,只需要增加一个品牌的子类就可以了,个数也是一个,不会影响到其他类。这显然符合开放-封闭原则。
而这里用到的合成/聚合复用原则是一个很有用处的原则,即优先使用对象的合成或聚合,而不是继承。究其原因是因为继承是一种强耦合的结构,父类变,子类就必须变。

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

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

相关文章

(二)汇编语句组成

一个完整的 RISC-V 汇编程序有多条 语句(statement) 组成。 一条典型的 RISC-V 汇编 语句 由 3 部分组成: 1.标签 List item label(标签): 标签是标识程序位置的记号。通常定义一个名称然后加上":"后缀。…

python连接hive报错:TypeError: can‘t concat str to bytes

目录 一、完整报错 二、解决 三、 其他报错 一、完整报错 Traceback (most recent call last): File "D:/Gitlab/my_world/hive2csv.py", line 18, in <module> conn hive.Connection(hosthost, portport, usernameusername, passwordpassword, data…

微机原理_14

一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中,选出一个正确的答案。&#xff09; 1,下面寻址方式的操作数不在存储器中的是(&#xff09; A. 堆栈寻址 B. 寄存器间址 C.寄存器寻址 D. 直接寻址 2,条件转移指令JNE的条件是(&#xff09; A. CF…

Linux入门必备指令

Linux学习之路起始篇——Linux基本指令 文章目录 Linux学习之路起始篇——Linux基本指令**一、ls指令****二、pwd命令****三、cd命令****四、touch指令****五、mkdir命令****六、rm命令****七、man 命令****八、cp命令****九、mv命令****10、cat 指令****十一、tac命令** 前言&…

基于AVR单片机的便携式心电监测设备设计与实现

基于AVR单片机的便携式心电监测设备是一种常用的医疗设备&#xff0c;用于随时监测和记录人体的心电信号。本文将介绍便携式心电监测设备的设计原理和实现步骤&#xff0c;并提供相应的代码示例。 1. 设计概述 便携式心电监测设备是一种小巧、方便携带的设备&#xff0c;能够…

【LSTM】北京pm2.5 天气预测--pytorch版本,有代码可以跑通-LSTM回归问题,工程落地一网打尽

文章目录 前言1. 知识理解1.1 核心理解1.2 原理1.2.1 图解LSTM1.2.1 分词1.2.1 英语的词表示1.2.2 中文的词表示1.2.3 构建词表 2. 工程代码2.1 数据预处理2.2 数据集&模型构建2.3 模型训练2.4 保持模型&加载模型&预测 前言 LSTM 少分析原理&#xff0c;更强调工程…

复杂数据统计与R语言程序设计实验一

1.下载并安装R语言软件&#xff0c;熟悉基本操作的命令及操作界面&#xff0c;掌握软件的使用方法&#xff08;提供学号加姓名的截图&#xff09;。 2.下载并安装Rstudio&#xff0c; &#xff08;提供运行代码及运行结果的截图&#xff09;。 3.下载并安装R包DT&#xff0c;…

Nginx - 本机读取服务器图像、视频

目录 一.引言 二.安装 Nginx 1.安装 By apt 2.安装 By 官网 三.配置 Nginx 1.Linux 机器配置 2.重启 Nginx 服务 3.本机查看机器文件 四.总结 一.引言 前面介绍了 GFP-GAN、PNG2GIF、GIF2PNG 等操作&#xff0c;我们生成的 video、gif、png 等形式的文件都存储在 lin…

软件测试/测试开发/人工智能丨基于Spark的分布式造数工具:加速大规模测试数据构建

随着软件开发规模的扩大&#xff0c;测试数据的构建变得越来越复杂&#xff0c;传统的造数方法难以应对大规模数据需求。本文将介绍如何使用Apache Spark构建分布式造数工具&#xff0c;以提升测试数据构建的效率和规模。 为什么选择Spark&#xff1f; 分布式计算&#xff1a;…

时间序列与 Statsmodels:预测所需的基本概念(1)

后文&#xff1a;时间序列与 statsmodels&#xff1a;预测所需的基本概念&#xff08;2&#xff09;-CSDN博客 一、说明 本博客解释了理解时间序列的基本概念&#xff1a;趋势、季节性、白噪声、平稳性&#xff0c;并使用自回归、差分和移动平均参数进行预测示例。这是理解任何…

Python将原始数据集和标注文件进行数据增强(随机仿射变换),并生成随机仿射变换的数据集和标注文件

Python将原始数据集和标注文件进行数据增强&#xff08;随机仿射变换&#xff09;&#xff0c;并生成随机仿射变换的数据集和标注文件 前言前提条件相关介绍实验环境生成随机仿射变换的数据集和标注文件代码实现输出结果 前言 由于本人水平有限&#xff0c;难免出现错漏&#x…

buildadmin+tp8表格操作(5)自定义组装搜索的查询

有时候我们会自定义组装一些数据&#xff0c;发送给后端&#xff0c;让后端来进行筛选&#xff0c;这里有一个示例 const onComSearchIdEq () > {// 展开公共搜索baTable.table.showComSearch true/*** 公共搜索表单赋值* 范围搜索有两个输入框&#xff0c;输入框绑定变量…

PLC梯形图实操——风扇正反转

文章目录 1.项目内创建函数块&#xff08;FB&#xff09;2.项目内创建数据块&#xff08;DB&#xff09;2.1去除优化块访问2.2去除优化块的访问后对数据块进行编译 3.在函数块&#xff08;FB&#xff09;内实现正转反转的自锁与互锁3.1在函数块内实现电机正反转的梯形图 4.主函…

【机器学习】037_暂退法

一、实现原理 具有输入噪音的训练&#xff0c;等价于Tikhonov正则化 核心方法&#xff1a;在前向传播的过程中&#xff0c;计算每一内部层的同时注入噪声 从作用上来看&#xff0c;表面上来说是在训练过程中丢弃一些神经元 假设x是某一层神经网络层的输出&#xff0c;是下一…

Linux进程通信——IPC、管道、FIFO的引入

进程间的通信——IPC 进程间通信 (IPC&#xff0c;InterProcess Communication) 是指在不同进程之间传播或交换信息。 IPC的方式通常有管道 (包括无名管道和命名管道) 、消息队列、信号量、共享存储、Socket、Streams等。其中 Socket和Streams支持不同主机上的两个进程IPC。 …

1230天,百度再见!!!

从2020年7月8日至2023年11月20日&#xff0c;在百度的工作到达了终点&#xff0c;完成了从学生向职场人的蜕变&#xff0c;是时候说再见了&#xff01; 一、成长收获 在这1230天里收获颇丰&#xff0c;下面与各位分享一下。 从技术至上到业务赋能的思想转变 相信很多人都存在“…

初始环境配置

目录 一、JDK1、简介2、配置步骤 二、Redis1、简介2、配置步骤 三、MySQL1、简介2、配置步骤 四、Git1、简介2、配置步骤 五、NodeJS1、简介2、配置步骤 六、Maven1、简介2、配置步骤 七、Tomcat1、简介2、配置步骤 一、JDK 1、简介 JDK 是 Oracle 提供的 Java 开发工具包&…

发币成功,记录一下~

N年前就听说了这样一种说法——“一个熟练的区块链工程师&#xff0c;10分钟就可以发出一个新的币” 以前仅仅是有这么一个认识&#xff0c;但当时并不特别关注这个领域。 最近系统性学习中&#xff0c;今天尝试发币成功啦&#xff0c;记录一下&#xff5e; 发在 Sepolia Tes…

EI论文程序:Adaboost-BP神经网络的回归预测算法,可作为深度学习对比预测模型,丰富实验内容,自带数据集,直接运行!

适用平台&#xff1a;Matlab 2021及以上 本程序参考中文EI期刊《基于Adaboost的BP神经网络改进算法在短期风速预测中的应用》&#xff0c;程序注释清晰&#xff0c;干货满满&#xff0c;下面对文章和程序做简要介绍。 为了提高短期风速预测的准确性&#xff0c;论文提出了使用…

【前端学java】java 中的数组(9)

往期回顾&#xff1a; 【前端学java】JAVA开发的依赖安装与环境配置 &#xff08;0&#xff09;【前端学 java】java的基础语法&#xff08;1&#xff09;【前端学java】JAVA中的packge与import&#xff08;2&#xff09;【前端学java】面向对象编程基础-类的使用 &#xff08…
最新文章