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

2023-10-29 18:52

本文主要是介绍设计模式大赏(一):桥接模式,组合模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

在这里插入图片描述

导言

本篇文章是设计模式大赏中的第一篇文章,这个系列的文章中我们主要将介绍一些常见的设计模式,主要是我在看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的视图层次。

使用组合模式的好处

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

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

这篇关于设计模式大赏(一):桥接模式,组合模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/302680

相关文章

hdu4869(逆元+求组合数)

//输入n,m,n表示翻牌的次数,m表示牌的数目,求经过n次操作后共有几种状态#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#includ

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

模版方法模式template method

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/template-method 超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。 上层接口有默认实现的方法和子类需要自己实现的方法

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

迭代器模式iterator

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/iterator 不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素

《x86汇编语言:从实模式到保护模式》视频来了

《x86汇编语言:从实模式到保护模式》视频来了 很多朋友留言,说我的专栏《x86汇编语言:从实模式到保护模式》写得很详细,还有的朋友希望我能写得更细,最好是覆盖全书的所有章节。 毕竟我不是作者,只有作者的解读才是最权威的。 当初我学习这本书的时候,只能靠自己摸索,网上搜不到什么好资源。 如果你正在学这本书或者汇编语言,那你有福气了。 本书作者李忠老师,以此书为蓝本,录制了全套视频。 试

利用命令模式构建高效的手游后端架构

在现代手游开发中,后端架构的设计对于支持高并发、快速迭代和复杂游戏逻辑至关重要。命令模式作为一种行为设计模式,可以有效地解耦请求的发起者与接收者,提升系统的可维护性和扩展性。本文将深入探讨如何利用命令模式构建一个强大且灵活的手游后端架构。 1. 命令模式的概念与优势 命令模式通过将请求封装为对象,使得请求的发起者和接收者之间的耦合度降低。这种模式的主要优势包括: 解耦请求发起者与处理者

springboot实战学习(1)(开发模式与环境)

目录 一、实战学习的引言 (1)前后端的大致学习模块 (2)后端 (3)前端 二、开发模式 一、实战学习的引言 (1)前后端的大致学习模块 (2)后端 Validation:做参数校验Mybatis:做数据库的操作Redis:做缓存Junit:单元测试项目部署:springboot项目部署相关的知识 (3)前端 Vite:Vue项目的脚手架Router:路由Pina:状态管理Eleme

状态模式state

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/state 在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。 在状态模式中,player.getState()获取的是player的当前状态,通常是一个实现了状态接口的对象。 onPlay()是状态模式中定义的一个方法,不同状态下(例如“正在播放”、“暂停

软件架构模式:5 分钟阅读

原文: https://orkhanscience.medium.com/software-architecture-patterns-5-mins-read-e9e3c8eb47d2 软件架构模式:5 分钟阅读 当有人潜入软件工程世界时,有一天他需要学习软件架构模式的基础知识。当我刚接触编码时,我不知道从哪里获得简要介绍现有架构模式的资源,这样它就不会太详细和混乱,而是非常抽象和易