当前位置: 首页 > news >正文

设计模式大赏(一):桥接模式,组合模式

设计模式大赏(一):桥接模式,组合模式

在这里插入图片描述

导言

本篇文章是设计模式大赏中的第一篇文章,这个系列的文章中我们主要将介绍一些常见的设计模式,主要是我在看Android源码中发现用到的一些设计模式。本篇文章将主要介绍桥接模式
组合模式 这两种设计模式。

本篇文章主要参考:《大话设计模式》

桥接模式

在这里插入图片描述

Android中的桥接模式

我一开始接触到桥接模式是在学习Android的WindowManager相关的源码过程中,具体来说,WindowManager的实现类WindowManagerImpl实际上并不直接实现相关的请求,而是将其委托给WindowManagerGlobal这个单例类来实现。这样将实现分为抽象和具体两部分的模式就叫做桥接模式

合成/聚合复用原则

在正式介绍到桥接模式之前我们需要先介绍一下合成聚合复用原则,该原则的核心思想就是:尽量使用合成和聚合,而不要去使用类的继承

聚合表示一种弱的拥有关系,即A对象可以包含B对象,但B对象不是A对象的一部分。比如说整个班级中可以包含我们个人,但是我们个人并不是班级的一部分,我们脱离开班级还是可以独立存在的,班级脱离我们也可以独立存在。

合成则表示一种强的拥有关系,比如说鸡翅对于鸡一样,显然鸡翅是鸡的一部分,他们的生命周期是一致的,谁也脱离不开谁。

但无论是聚合还是合成关系,他们的耦合强度都要低于继承,继承是一种强耦合的关系,遵循合成/聚合复用原则可以防止类发展成一个难以管理的庞然大物。

桥接模式的概念

桥接模式(Bridge),是一种将抽象部分与它的实现部分分离,使他们都可以独立变化的一种设计模式。

下面是一个标准的桥接模式的基本模板:
在这里插入图片描述
实际上这样说还是很抽象,我们可以借用大话设计模式中的例子来说明:
比如说对手机来说,我们可以将其拆分出两个抽象的概念:手机的硬件和手机的软件,对于我们Android端来说,各个手机厂商的硬件之间都是高度定制化的,所以我们可以将其简化为手机厂商的品牌和手机的软件这两个抽象:

在这里插入图片描述
显然各个品牌手机的手机都会持有各自的手机软件,但是手机软件并不是属于手机的一部分,这是一种聚合持有的关系。这样分类的原因就是为了方便手机品牌和手机软件之间各自的拓展:即为每个抽象添加功能不涉及到其他类的修改。

实际上,我觉得桥接模式强调的就一点:通过多个角度将一个系统进行切分,使各个部分在变化的时候不影响其他部分的变化。

这样做的好处有:

  1. 使系统更加灵活,能够独立地扩展和变化抽象部分和实现部分。
  2. 提高了系统的可维护性和可扩展性,因为可以通过添加新的抽象或实现类来扩展系统。

桥接模式的具体示例

为了更好地理解,接下来引入一个具体的实例:比如说我们想要生产瓶装饮料的话,就可以将这整个罐装饮料抽象成两个部分:装饮料的瓶子和具体的饮料

在这里插入图片描述
下面是我的示例代码:

fun main() {val Glass:Bottle = GlassBottle(Cola())val Plastic:Bottle = PlasticBottle(Sprite())val Bridge = BottleBridgeImpl()Bridge.LoadDrink(Glass)Bridge.LoadDrink(Plastic)
}
//抽象类-瓶子
abstract class Bottle(var mDrinks:Drinks) {//制作瓶子的方法abstract fun MakeBottle()}
//抽象类-饮料
abstract class Drinks{//生产饮料的方法abstract fun MakeDrinks()
}
//抽象出连接上面两个抽象类的桥接方法
interface BottleBridge{//装瓶的方法fun LoadDrink(bottle:Bottle)
}class BottleBridgeImpl():BottleBridge{override fun LoadDrink(bottle: Bottle) {println("压缩装瓶,倒入${bottle.mDrinks}")}
}class GlassBottle(mDrinks: Drinks):Bottle(mDrinks) {override fun MakeBottle() {println("生产玻璃瓶")}
}class PlasticBottle(mDrinks: Drinks):Bottle(mDrinks) {override fun MakeBottle() {println("生产塑料瓶")}
}class Cola():Drinks(){override fun MakeDrinks() {println("生产可乐")}override fun toString(): String {return "可乐"}
}class Sprite():Drinks() {override fun MakeDrinks() {println("生产雪碧")}override fun toString(): String {return "雪碧"}
}

此处我将饮料和瓶子这两部分抽象出来,并引入了一个连接这两个部分的桥接接口,这样饮料和瓶子这两个抽象概念在变化的过程只需要维护自身的制造方法即可而不需要关注其他部分。

总而言之,我觉得桥接模式的核心就是从多个维度将一个系统进行拆分,抽象出各个抽象部分,然后各个抽象部分各自有自己的实现,使得一个抽象部分的具体实现变化时不影响其他的部分。

组合模式

在这里插入图片描述

组合模式的概念

组合模式,是将对象组合成树形结构以表示整体-部分的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性

这整个描述里有两个关键字:树形结构以及一致性。这里我们可以以一个学校的管理为例,学校的管理系统首先是一个大的全局的学校管理系统,向下细分又可以分为学院管理系统,再向下还可以分为各个专业的管理系统,这整个结构是一个树形的结构;而对于各个层级的管理系统我们肯定希望他们对具体信息的操作是一致的,比如说我们可以在学院管理系统对学生A进行加分操作,也可以在专业管理系统中对学生A进行加分操作,这个加分操作无论是在哪个层级的管理系统中发起的都应该有一致的效果,这就是一致性

下面是组合模式的典型结构图:
在这里插入图片描述

Android中的组合模式

说到这里是不是觉得这个组合模式很像Android中ViewGroup和View的组合关系,实际上确实如此,通过使用组合模式,Android开发人员可以更容易地管理和操作UI元素,以便以可扩展和灵活的方式构建用户界面。每个 ViewGroup 作为容器可以包含多个子 View,从而形成了整个布局的层次结构。
在这里插入图片描述

何时使用组合模式

使用组合模式的最佳场景就是当你发现需求中体现的是整体与部分层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象时,此时就应该考虑使用组合模式了,在上面说到了Android整个视图层次就是用到了组合模式,实际上Java上的UI层次也类似。

这个组合模式如果理解了Android中View的视图层次应该就很形象了,此处就不再另加例子,大家可以去看看Android中View的视图层次。

使用组合模式的好处

使用组合模式的好处,首先我觉得如果体现的是整体与部分的层次结构时,使用组合模式显然可以让整个需求的层次更加清晰

其次,用户不用关心这到底是一个组件组还是一个组件,简单来说组合模式让用户可以一致地使用组合结构和单个对象。

相关文章:

设计模式大赏(一):桥接模式,组合模式

设计模式大赏(一):桥接模式,组合模式 导言 本篇文章是设计模式大赏中的第一篇文章,这个系列的文章中我们主要将介绍一些常见的设计模式,主要是我在看Android源码中发现用到的一些设计模式。本篇文章将主要…...

数据通信——应用层(DHCP的原理与配置)

引言 假如我们的网络中有N台设备,它们都要设置IP地址,如果人工去一个个配置不仅不方便管理还很麻烦。因此我们用DHCP来自动分配地址。 一,系统的启动流程 不仅是计算机、很多网络设备的启动流程如下: 设备上电后,硬件…...

力扣151.反转字符串中的单词

原题链接&#xff1a;力扣151.反转字符串中的单词 全代码&#xff1a; 需要复刷 class Solution { public:void reverse(string& s, int start, int end){ //翻转&#xff0c;区间写法&#xff1a;左闭右闭 []for (int i start, j end; i < j; i, j--) {swap(s[i],…...

vim三种模式,文本操作(操作字符/光标,列出行号可视化块模式/多文件查看)

目录 vim--文本编辑器 功能 基本概念 命令/默认模式 插入模式 底行模式 文本操作 引入 移动光标位置 删除字符 -- x/dd 复制/粘贴字符 -- yw/yyp 替换文本 -- r / %s 底行模式 全局替换 -- /g 撤销操作 -- u / ctrlr 修改字符 -- cw 示例 跳行 -- ctrlg 底行…...

jquery控制easyui中combobox、textbox显示隐藏

//combobox下拉框 $("#下拉框id.combo").hide();//textbox输入框 $("#输入框id.textbox").hide(); 参考网址&#xff1a; https://blog.csdn.net/Coldmood/article/details/128279727...

Android拖放startDragAndDrop拖拽onDrawShadow静态添加xml布局View,Kotlin(4)

Android拖放startDragAndDrop拖拽onDrawShadow静态添加xml布局View&#xff0c;Kotlin&#xff08;4&#xff09; import android.content.ClipData import android.graphics.Canvas import android.graphics.Point import android.os.Bundle import android.util.Log import a…...

Servlet 初始化参数(web.xml和@WebServlet)

1、通过web.xml方式 <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://xmlns.jcp.org/xm…...

shell_62.shell脚本生成一个标准的 SQL INSERT 语句

无论是将文件读入脚本&#xff0c;还是将数据从脚本输出到文件&#xff0c;都会用到文件重定向&#xff0c;这是一种很 常见的操作。本节中的示例脚本两种功能皆有。它会读取 CSV 格式的数据文件&#xff0c;输出 SQL INSERT 语句&#xff0c;并将数据插入数据库。 shell 脚本使…...

华为ICT——第五章语音处理理论与实践

目录 语言学&#xff1a; 主要应用场景&#xff1a; 语言学&#xff1a; 语言学&#xff1a; 语音学&#xff08;1&#xff09; 语音学&#xff08;2&#xff09; 语音处理介绍&#xff1a; 人类语音的来源&#xff1a; 语言数据&#xff1a; 语言信号预处理&#xff1a; …...

ardupilot开发 --- SLAM 篇

1. 视觉SLAM 1.1 深度相机的种类 结构光相机&#xff0c;如 Kinect1.0、RealSenseTOF相机&#xff0c;如 Kinect2.0双目相机&#xff0c;如 ZED详细参考&#xff1a;https://zhuanlan.zhihu.com/p/282776636 1.2 视觉SLAM算法 2D slam 与3D slam 应用场景有哪些不同&#x…...

Elasticsearch:在你的数据上训练大型语言模型 (LLM)

过去的一两年&#xff0c;大型语言模型&#xff08;LLM&#xff09;席卷了互联网。 最近 Google 推出的 PaLM 2 和 OpenAI 推出的 GPT 4激发了企业的想象力。 跨领域构思了许多潜在的用例。 多语言客户支持、代码生成、内容创建和高级聊天机器人都是一些例子。 这些用例要求 LL…...

拓展卡尔曼滤波EKF

How to fusion two Gauss Distribution N ( x , μ 0 , σ 0 ) N ( x , μ 1 , σ 1 ) N ( x , μ ′ , σ ′ ) \begin{equation} \begin{aligned} \mathcal{N}(x,\mu_0,\sigma_0) \mathcal{N}(x,\mu_1,\sigma_1) \mathcal{N}(x,\mu,\sigma) \\ \end{aligned} \end{equatio…...

第四章 应用SysML基本特性集的汽车示例 P2(断更)|系统建模语言SysML实用指南学习

仅供个人学习 使用试用版CSM很鸡肋&#xff0c;然后书中一些内容没有说明&#xff0c;自定义方面有点困难&#xff0c;第四章暂时停止 同时感觉画图的顺序也很随意&#xff1f;甚至需求图放在了后面&#xff0c;觉得很离谱。 准备跳过这一章节 汽车模型 续P1 序列图表示启…...

Vue入门——核心知识点

简介 Vue是一套用于构建用户界面的渐进式JS框架。 构建用户界面&#xff1a;就是将后端返回来的数据以不同的形式(例如&#xff1a;列表、按钮等)显示在界面上。渐进式&#xff1a;就是可以按需加载各种库。简单的应用只需要一个核心库即可&#xff0c;复杂的应用可以按照需求…...

使用opencv的tracking模块跟踪目标

OpenCV跟踪模块算法介绍 OpenCV的tracking模块是一个功能强大的跟踪算法库&#xff0c;包含多种用于跟踪对象的算法。它可以帮助你在连续的视频帧中定位一个物体&#xff0c;例如人脸、眼睛、车辆等。 在OpenCV的tracking模块中&#xff0c;一些主要的跟踪算法包括&#xff1…...

Debian或Ubuntu静态交叉编译arm和aarch64

Debian或Ubuntu静态交叉编译arm和aarch64 介绍术语ARM架构前置条件从源代码编译一个简单的C程序configure和make交叉编译关于静态链接和依赖关系使用 musl libc 实现与 configure 和 make 进行交叉编译 ARM 正在获得越来越多的关注&#xff0c;并且越来越受欢迎。直接在这些基于…...

最新ai系统ChatGPT程序源码+详细搭建教程+以图生图+Dall-E2绘画+支持GPT4+Midjourney绘画

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…...

【设计模式】第16节:行为型模式之“命令模式”

一、简介 命令模式&#xff1a;将请求&#xff08;命令&#xff09;封装为一个对象&#xff0c;这样可以使用不同的请求参数化其他对象&#xff08;将不同请求依赖注入到其他对象&#xff09;&#xff0c;并且能够支持请求&#xff08;命令&#xff09;的排队执行、记录日志、…...

安装pytorch报错torch.cuda.is_available()=false的解决方法

参考文章&#xff1a; https://blog.csdn.net/qq_46126258/article/details/112708781 https://blog.csdn.net/Andy_Luke/article/details/122503884 https://blog.csdn.net/anmin8888/article/details/127910084 https://blog.csdn.net/zcs2632008/article/details/127025294 …...

自定义表格的表头根据后端的数据进行筛选是否进行自定义表头添加按钮

自定义表格的表头根据后端的数据进行筛选是否进行自定义表头添加按钮 自定义表格的表头根据后端的数据进行筛选是否进行自定义表头添加按钮 <template><div class"box"><el-table :data"msgMapList" border class"table">&l…...

Gemini深度研究模式性能跃迁实录:单次查询响应缩短68%,附12项可复用Prompt工程Checklist

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;Gemini深度研究模式性能跃迁实录 Gemini深度研究模式&#xff08;Deep Research Mode&#xff09;并非简单调用多轮API&#xff0c;而是通过动态规划推理路径、自适应检索增强与跨文档语义对齐三大机制&#x…...

英雄联盟智能助手:League Akari 的5大核心功能深度解析

英雄联盟智能助手&#xff1a;League Akari 的5大核心功能深度解析 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power &#x1f680;. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League Akari 是一款基于英…...

VisualGGPK2终极指南:5步轻松编辑《流放之路》游戏资源文件

VisualGGPK2终极指南&#xff1a;5步轻松编辑《流放之路》游戏资源文件 【免费下载链接】VisualGGPK2 Library for Content.ggpk of PathOfExile (Rewrite of libggpk) 项目地址: https://gitcode.com/gh_mirrors/vi/VisualGGPK2 VisualGGPK2是一款专为《流放之路》玩家…...

保姆级教程:在Windows电脑上免梯子安装GPT4All最新版(附模型下载避坑指南)

Windows系统本地部署GPT4All全流程指南&#xff1a;从零基础到高效运行最近半年&#xff0c;开源大语言模型生态中最令人兴奋的变化之一&#xff0c;就是像GPT4All这样的工具让普通开发者也能在消费级硬件上运行强大的AI模型。作为一名长期关注AI本地化部署的技术顾问&#xff…...

多重插补与MICE:量化ESG评分不确定性的工程实践

1. 项目概述&#xff1a;当ESG评分遇上数据“黑洞”&#xff0c;我们如何量化不确定性&#xff1f;在金融和可持续投资领域&#xff0c;ESG评分正成为评估公司长期价值与风险的关键标尺。然而&#xff0c;从业者们都心知肚明一个公开的秘密&#xff1a;支撑这些评分的底层数据&…...

终极iOS设备激活解锁解决方案:Applera1n完全指南

终极iOS设备激活解锁解决方案&#xff1a;Applera1n完全指南 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 你是否曾经遇到过二手iPhone或iPad无法激活的困境&#xff1f;当你满怀期待地拿到一台设备…...

终极鼠标抖动工具指南:告别电脑休眠困扰的简单解决方案

终极鼠标抖动工具指南&#xff1a;告别电脑休眠困扰的简单解决方案 【免费下载链接】mousejiggler Mouse Jiggler is a very simple piece of software whose sole function is to "fake" mouse input to Windows, and jiggle the mouse pointer back and forth. 项…...

ChatGPT提示工程进阶实战(故事化表达失效的7大隐形陷阱)

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;故事化表达失效的底层认知重构 当工程师在技术文档中反复使用“用户点击按钮后&#xff0c;系统就像一位耐心的向导&#xff0c;带他走过三步旅程”这类修辞时&#xff0c;信息熵并未降低——反而因隐喻失准而…...

LogExpert深度解析:企业级日志分析平台的架构设计与实战应用

LogExpert深度解析&#xff1a;企业级日志分析平台的架构设计与实战应用 【免费下载链接】LogExpert Windows tail program and log file analyzer. 项目地址: https://gitcode.com/gh_mirrors/lo/LogExpert LogExpert是一款面向Windows平台的专业级日志分析工具&#x…...

一键永久保存:用novel-downloader打造你的个人数字图书馆 [特殊字符]

一键永久保存&#xff1a;用novel-downloader打造你的个人数字图书馆 &#x1f4da; 【免费下载链接】novel-downloader 一个可扩展的通用型小说下载器。 项目地址: https://gitcode.com/gh_mirrors/no/novel-downloader 在信息飞速更迭的互联网时代&#xff0c;你是否曾…...