设计模式13——桥接模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用,主要是下面的UML图可以起到大作用,在你学习过一遍以后可能会遗忘,忘记了不要紧,只要看一眼UML图就能想起来了。同时也请大家多多指教。

桥接模式(Bridge)

是一种结构型模式。

目录

一、概述

1.1、主要的角色(如果有点懵的话就先跳过着小部分):

1.2、直观的理解桥接模式要干什么:

1.3、上述手机应用例子的UML图:

二、桥接模式的模板

2.1、对象之间的关系用UML图表示如下:

2.2、Java版的代码如下:


一、概述

1、将抽象部分与它的实现部分分离,使它们都可以独立地变化;
2、(实现:是指抽象类以及抽象类的派生类,对于它们的实现类。)这些实现类应该分离;
3、和 合成|聚合复用原则 相关;
4、实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。

1.1、主要的角色(如果有点懵的话就先跳过)

主要的角色分两种,但从代码(或技术)实现的角度看(为了充分使用面向对象语言的3大特性封装、继承、多态,还另外需要抽象类或接口)可能有4个:

  1. 实现类:实现类的抽象类或接口 +实现类
  2. 新提取的类:新提取的类的抽象类或接口 +新提取的类的实现类

1.2、直观的理解桥接模式要干什么:

以手机应用软件为例,我们有各种需要,如想和人聊天,那么就用微信;如想购物,那么就用淘宝等。并且对于我们不同的手机,有着不同的操作系统,一样可以使用这些软件来满足我们某方面的需求。

现在假设你是应用程序开发者,你需要在开发出微信和淘宝,并且你还要让它们可以在鸿蒙或者苹果手机上运行:

如果按照以前的思路,那肯定是把微信开发两个版本分别运行在鸿蒙和苹果系统上,同样淘宝也是开发两个,这个例子比较简单,这样做的话只要设计四个对象即可,但万一又有新的需求这样就并不一定好使了。就假设现在要开发10个软件,并且都适配4个系统,那么按照以前的思路,那你需要设计 10*4=40 个对象, 如果再多点呢,那工作量将是难以想象,并且你也清除有很多重复适配工作的。

我们可以这样,把操作系统和应用软件分开看:

  • 应用软件都定义一个统一的接口,每个应用软件只针对自己要完成的功能进行实现,如微信对接口具体实现的是聊天,淘宝对接口的具体实现是购物。
  • 操作系统也都定义一个统一的运行应用程序的接口,每个操作系统针对接口的具体实现是完成对任何一个应用软件对象的正常运行。

这样再结合多态,就可以实现上面概念里的第一句话,‘将抽象部分与它的实现部分分离,使它们都可以独立地变化’,也就是抽象分离出两部分:操作系统 + 应用软件;

并且它们两可以独立增加或减少。

此时你可能会发现对于手机应用程序来说他有着不同的维度,如功能维度和运行环境维度。像这种一个事物但是对应多个维度,也就是说某个目标对象可以被抽象出多个抽象类,那么就可以尝试使用桥接模式,这样也就符合合成|聚合复用原则。

(想简单了解原则的可以点击下面链接)

设计模式2——原则篇极简版

1.3、上述手机应用例子的UML图:

这样子,把操作系统和应用软件分开,那么就需要建6个类。(对于之前说的‘要开发10个软件,并且都适配3个系统’的话,就不需要40个对象了,而是10+4+2=16个对象。其中有2个是操作系统和应用软件的抽象类)

如何使用?(也就是主程序要怎么调用这些对象)

先填装在使用。

如:可以给鸿蒙系统填装一个应用,然后调用操作系统的运行接口就可以让此应用运行。

(注:本例是以操作系统和应用程序看成一个一个类对象为角度,从而可以让操作系统和应用各自实现各自的统一接口,而现实生活中并非如此) 

对应上文的角色分类,在本例种,把应用软件看为解决原本问题的实现类,而操作系统是在此基础上又新提取或抽象出的新提取的类。从代码角度讲:新提取的类是主程序最终调用的类,而实现类是被新提取的类调用,刚好对应我们点击图标后,操作系统接收到我们触摸屏幕的信号,然后再启动应用程序。

(再举例:物品-----对应颜色维度和形状维度)

二、桥接模式的模板

2.1、对象之间的关系用UML图表示如下:

2.2、Java版的代码如下:

实现类(抽象):

abstract class Implementor {public abstract void operation();
}

具体的实现类1:

public class ConcreteImplementor1 extends Implementor{@Overridepublic void operation() {System.out.println("具体实现1的方法执行");}
}

具体的实现类2:

public class ConcreteImplementor2 extends Implementor{@Overridepublic void operation() {System.out.println("具体实现2的方法执行");}
}

抽象分类对象(抽象):

abstract class Abstraction {protected Implementor implementor;public void setImplementor(Implementor implementor) {this.implementor = implementor;}public abstract void operation();
}

提炼后的抽象分类对象A:

public class RefinedAbstractionA extends Abstraction {@Overridepublic void operation() {System.out.println("提炼后的A");implementor.operation();}
}

提炼后的抽象分类对象B:

public class RefinedAbstractionB extends Abstraction {@Overridepublic void operation() {System.out.println("提炼后的B");implementor.operation();}
}

主程序(发起请求的类):

public class Main {public static void main(String[] args) {Abstraction abstraction;abstraction = new RefinedAbstractionA();abstraction.setImplementor(new ConcreteImplementor1());abstraction.operation();abstraction.setImplementor(new ConcreteImplementor2());abstraction.operation();System.out.println("------------------");abstraction = new RefinedAbstractionB();abstraction.setImplementor(new ConcreteImplementor1());abstraction.operation();abstraction.setImplementor(new ConcreteImplementor2());abstraction.operation();}
}

这里暂时就不再例其它编程语言的例子了,可以把上面的Java例子复制到你本地,运行main函数试一下加深理解。这些代码都是我自己学习的时候根据一些教材手敲的,不存在bug可以直接运行。

如果觉得本文还不错,就请点个赞给作者一点鼓励吧!如果有建议,也请评论指教和讨论!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

存储器和CPU的连接与TCP的流量控制

存储器与CPU的连接 存储容量的拓展 (1)位拓展:增加存储字长 (2)字拓展 增加存储器字的数量 例题:设CPU有16根地址线,8根数据线,并用MREQ作为访问存储控制信号(低电平有效),WR作为…

建议大家少用点儿网站测速工具

春节休息期间明月有接了几个服务器代运维的业务,期间就发现不少新手站长们还在用 17ce、站长工具等等这些网站测速工具来评判站点访问速度的,感觉很有必要给大家聊聊这个事儿,因为这毕竟也是一个涉及服务器安全的一个重要环节了。 其实&#…

C++ list类

目录 0.前言 1.list介绍 1.1优势 1.2劣势 1.3容器属性 2.list使用 2.1构造函数 2.1.1默认构造函数 2.1.2填充构造函数 2.1.3范围构造函数 2.1.4拷贝构造函数 2.1.5初始化列表构造函数 2.2迭代器 2.2.1 begin() 2.2.2 end() 2.2.3 cbegin() 2.2.4 cend() 2.2.…

100个 Unity小游戏系列四 -Unity 抽奖游戏专题二 水果机游戏

一、演示效果 二、知识点 2.1 布局 private void CreateItems(){for (int i 0; i < rewardDatas.Length; i){var reward_data rewardDatas[i];GameObject fruitOjb;if (i < itemRoot.childCount){fruitOjb itemRoot.GetChild(i).gameObject;}else{fruitOjb Instant…

MATLAB分类与判别模型算法: 快速近邻法(FastNN)分类程序【含Matlab源码 MX_005期】

算法思路介绍&#xff1a; 1. 数据准备阶段&#xff1a; 生成一个合成数据集 X&#xff0c;其中包含三个簇&#xff0c;每个簇分布在不同的区域。 定义聚类层数 L 和每个层次的子集数量 l。 2. 聚类阶段&#xff1a; 使用K均值聚类算法将初始数据集 X 分成 l 个簇。…

mac m1安装homebrew管理工具(brew命令)完整流程

背景 因为mac上的brew很久没用了&#xff0c;版本非常旧&#xff0c;随着mac os的更新&#xff0c;本机的homebrew大部分的功能都无法使用&#xff0c;幸好过去通过brew安装的工具比较少&#xff0c;于是决定重新安装一遍brew。 卸载旧版brew 法一&#xff1a;通过使用线上…

【PB案例学习笔记】-13 徒手做个电子时钟

写在前面 这是PB案例学习笔记系列文章的第11篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

渗透测试工具Cobalt strike-2.CS基础使用

三、结合metasploit,反弹shell 在kali中开启使用命令开启metasploit msfconsole ┌──(root㉿oldboy)-[~] └─# msfconsole --- msf6 > use exploit/multi/handler [*] Using configured payload generic/shell_reverse_tcp --- msf6 exploit(multi/handler) > show …

【5.基础知识和程序编译及调试】

一、GCC概述&#xff1a;是GUN推出的多平台编译器&#xff0c;可将C/C源程序编译成可执行文件。编译流程分为以下四个步骤&#xff1a; 1、预处理 2、编译 3、汇编 4、链接 注&#xff1a;编译器根据程序的扩展名来分辨编写源程序所用的语言。根据不同的后缀名对他们进行相…

058.最后一个单词的长度

题意 给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 难度 简单 示例 1&#xff1a; 输入&#xff1a;s "Hello World" 输…

excel表格里怎样不删除0,又不显示0呢?

在单元格里不显示0&#xff0c;大体上有这么几种方法&#xff1a; 1.设置单元格自定义格式 选中数据区域&#xff0c;鼠标右键&#xff0c;点一下设置单元格格式&#xff0c;选中数字&#xff0c;自定义&#xff0c;在右侧的类型栏&#xff0c;设置格式&#xff1a; [0]&quo…

android11禁止进入屏保和自动休眠

应某些客户要求&#xff0c;关闭了开机进入屏保&#xff0c;一段时间会休眠的问题。以下diff可供参考&#xff1a; diff --git a/overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml b/overlay/frameworks/base/packages/SettingsProvider/res/value…

《微服务王国的守护者:Spring Cloud Dubbo的奇幻冒险》

5. 经典问题与解决方案 5.3 服务追踪与链路监控 在微服务架构的广袤宇宙中&#xff0c;服务间的调用关系错综复杂&#xff0c;如同一张庞大的星系网络。当一个请求穿越这个星系&#xff0c;经过多个服务节点时&#xff0c;如何追踪它的路径&#xff0c;如何监控整个链路的健康…

ssm校园疫情防控管理系统-计算机毕业设计源码30796

目 录 摘要 1 绪论 1.1目的及意义 1.2开发现状 1.3ssm框架介绍 1.3论文结构与章节安排 2 校园疫情防控管理系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分…

手摸手教你uniapp原生插件开发

行有余力,心无恐惧 这篇技术文章写了得有两三个礼拜,虽然最近各种事情,工作上的生活上的,但是感觉还是有很多时间被浪费.还记得几年前曾经有一段时间7点多起床运动,然后工作学习,看书提升认知.现在我都要佩服那会儿的自己.如果想回到那种状态,我觉得需要有三个重要的条件. 其…

[ C++ ] 深入理解模板( 初 阶 )

函数模板 函数模板格式 template <typename T1, typename T2,......,typename Tn> 返回值类型 函数名(参数列表){} 注意&#xff1a; typename是用来定义模板参数关键字&#xff0c;也可以使用class(切记&#xff1a;不能使用struct代替class) 函数模板的实例化 模板参数…

Simulink从0搭建模型07-P8for循环的使用

Simulink从0搭建模型07-P8for循环的使用 今日学习内容1. For Iterator Subsystem模块介绍1.1. 累加器1.2. For Iterator1.3.小结 2. states介绍3. Set next i&#xff08;相当break)学习心得 今日学习内容 b站视频 【Simulink 0基础入门教程 P8 for循环的使用 For Itrator Sub…

前端中 dayjs 时间的插件使用(在vue 项目中)

Day.js中文网 这是dayjs的中文文档 里面包括了使用方法 下面我来详细介绍一下这个插件的使用 Day.js 可以运行在浏览器和 Node.js 中。 一般咱直接是 npm 安装 npm install dayjs 目前应该使用的是Es6 的语法 import dayjs from dayjs 当前时间 直接调用 dayjs() 将返回…

组件的传参等

一:组件的生命周期函数 组件的生命周期函数: created只是创建了组件内的实例对象 attached,给组件实例绑定了属性,绑定到页面节点树之后 ready准备好渲染之后,还未渲染之前 moved组件实例被移动到另一个位置后执行 detached在整个组件被被移除执行 error执行的时候,组件内…

乡村振兴的乡村产业创新发展:培育乡村新兴产业,打造乡村产业新名片,促进乡村经济多元化发展

目录 一、引言 二、乡村产业创新发展的必要性 &#xff08;一&#xff09;适应新时代发展要求 &#xff08;二&#xff09;满足消费升级需求 &#xff08;三&#xff09;促进农民增收致富 三、培育乡村新兴产业策略 &#xff08;一&#xff09;加强科技创新引领 &#…