快速理解24种设计模式

news2024/12/27 3:16:07

简单工厂模式

建立产品接口类,规定好要实现方法。

建立工厂类,根据传入的参数,实例化所需的类,实例化的类必须实现指定的产品类接口

创建型

单例模式Singleton

保证一个类只有一个实例,并提供一个访问他它的全局访问点

懒汉式:调用获取单例方法,才进行实例化

饿汉式:类初始化时即生成了实例

工厂方法模式Factory(类)

定义一个创建对象的接口,让子类决定实例化那一个类

在简单工厂模式的基础上,将工厂也进行抽象,工厂类实现工厂接口。工厂接口只对指定的一个产品进行实例化。

抽象工厂模式Abstract Factory

提供一个创建一系列相关或互相依赖对象的接口,而无需指定他们的具体类

在简单工厂方法模式的基础上,对工厂接口进行扩展,接口中可以定义多个方法,每个方法产生不同产品类的实例。

原型模式Prototype

用原型实例指定创建的对象种类,并复制原型中的属性给新创建的对象

即类中实现克隆自己的方法,供外部调用。

但是现在很多高级语言已经自带了clone方法,可以克隆对象,那么原型模式还有什么用呢。这是因为有时候语言中自带的clone方法存在一定的局限性。

以java为例,java中的clone,克隆出的新对象中的引用类型属性,是对原对象中属性的引用,他们内存地址是相同的。如果对克隆对象的属性进行操作,可能会修改原对象的信息。这个时候我们就需要重新实现clone,实现真正的克隆。这就要求参与功能的类都需要实现克隆接口

详解Java中的clone方法 -- 原型模式_java clone-CSDN博客 这篇文章对这个问题进行了详细的说明

建造者模式Builder

将一个复杂对象的构建与他的表示分离,使同样的构建过程可以创建不同的表示

  • 也叫生成器模式,当类的初始化过程需要设置很多属性且过程复杂时,一次性把所有参数传入构造函数中显得非常不优雅。我们可以把这些属性的设置过程拆分到各个个方法中去,每个方法中设置属性后,返回类本身。这样,在使用时我们可以以链式操作的形式配置参数和调用方法。yii2框架中的query操作就是典型的使用。
  • 以上属于是建造者模式的进阶模式,在方法层面就实现了建造者模式。如果严格按照建造者模式的类图,则是在类层面实现建造者模式,如下

当创建了一个建造者类B1,他的BuilderPart方法中,调用了Product的F1,F2方法设置了属性,我们就获取了一个拥有F1,F2状态的product对象。

当我们想要获取一个设置了F2,F3属性的product对象时,就需再在创建一个建造者类。符合开闭原则。

结构型

组合模式Composite

把对象组合成树形结构,以表示整体-部分的层次结构,使单个对象与组合对象的使用具有一致性

主要解决整体和部分的关系。比如全国人口统计,每个省,每个市,每个县都需要完成各自辖区的人口统计,但是实现方式不一样。统计全国人口时,不关心统计方法的内部代码,只需要拿到统计方法的值即可。

该模式基于容器实现,容器本身和传入容器的对象(即每个地区的人口统计)都要实现同一个统计接口。完成数据组合后(即往容器中加入子对象),调用容器的统计方法遍历执行列表中对象的统计方法即可,关键代码如下

适配器模式Adapter (类&对象)

将一个类的接口转换为客户希望的另一个接口。使原本因接口不兼容无法一起工作的类可以一起工作。

主要目的是将一个类的接口转换成客户希望的另外一个接口。

基本使用流程为:创建一个适配器类,类的属性为待适配的对象,类的方法为目标方法。除目标方法外,还有一个方法用于接收传入的适配对象,并赋值给待适配属性对象,然后就可以在各个目标方法中调用适配对象的对应方法

装饰器模式Decorator

无需继承,动态的给一个对象添加额外的功能

主要实现:不使用继承,对已有类的方法进行扩展和增加。

实现方式与适配器模式很相似,区别是创建的装饰器类必须实现被扩展类中的方法,这些方法中可以调用被扩展类的原有方法并进行扩展。也可以添加新的方法,实现新的功能。

代理模式Proxy

为一个对象提供一个代理,只能通过代理访问对象

代理模式与适配器模式、装饰器模式类似。不同点是,代理类中的方法只需与被代理类保持一致即可,不需增加和适配

桥接模式Bridge

将抽象部分与实现部分分离,使他们都可以独立变化

一个类存在两个(或多个)独立变化的维度,我们通过组合的方式,让这两个(或多个)维度可以独立进行扩展。通过组合关系来替代继承关系,避免继承层次的指数级爆炸。

策略模式是对算法的抽象,调用者可以根据不同的情况,自主选择不同的算法实现。桥接模式是策略模式的升级版,不仅对算法实现进行抽象,对于调用者也进行抽象,让系统扩性更好,更灵活。世界没有免费的午餐,灵活性变高了,但是复杂性也变高了,对程序员的要求也更高。

桥接模式中,可能存在多个角色,这些角色都要抽象出对应的接口供各自的角色实现,并根据需求依次作为其他角色的使用者

例如角色A实现了sendA()方法,角色B是A的使用者,接收A并处理后,在sendB()方法中执行A的sendA()方法,此时A的sendA()方法输出已经发生了改变。如果存在角色C,那么角色C就会接收B,并在自己的sendC方法中调用sendB()方法。

这个过程中,原数据在各个角色之间被交接和处理,各个角色就像桥一样连接在一起,把数据从开始送到结束,实现了输出。

https://zhuanlan.zhihu.com/p/112497289 该文章中的桥接模式代码描述的比较清晰

外观模式Facade

给系统中的一组接口提供一个高层次的调用接口,使系统更加容易使用

通过创建一个类,在类的方法中将多个功能和步骤有序的执行,外部调用时,只需要调用类的一个方法即可,不需要关心方法内部各个功能的执行顺序和关系。

这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。不符合开闭原则,新增需求时要修改外观类

享元模式(FlyWeight)

使用共享技术支持大量细粒度对象

即连接池技术,通过维护一个对象的集合,通过集合对集合内的对象进行共享。当使用时,先查询集合内是否有可用对象,使用完毕时,释放对象(即修改对象的使用状态)

行为型

命令模式Command

将一个请求封装为一个对象,从而可以使用不同的请求对象对客户端进行参数化

命令模式与外观模式很像,都是对一系列功能进行组织和调用。不同的是,命令模式不需要将这些调用步骤封装到一个类里,可以实时添加或撤销某一步操作。类似mvc架构中的控制器,在控制器方法中可以将请求、数据、视图等功能进行组织和执行。

详细代码示例如下:

责任链模式Chain of Responsibility

使多个对象都有机会处理请求,避免发送者与接收者之间的耦合关系

责任链模式与过滤器模式类似,都是对一个对象进行一系列处理,处理类都是实现相同接口或抽象的类。不同点是,责任链模式中的处理流程是提前准备好的。每个处理类在实例化时,必须指定下一个处理对象,直到最后一个处理类时,无需再指定。一旦对象在某个处理对象中被处理,则不在进行后续的步骤。

解释器模式Interpreter (类)

针对语言或算法,定义一个解释器,用以表示语言中的句子

解释器模式类似过滤器模式,只不过侧重点不同。过滤器侧重对数据的过滤删除,而解释器则侧重对数据的解释和修改

迭代器模式Iterator

提供一种方法顺序访问一个聚合对象中各个元素,且不需暴露对象的内部表示

用于顺序访问集合对象的元素,其实就是工厂方法模式的具体使用。

首先定义一个迭代器接口,接口中包hasNext()和next()方法,之后实现多个迭代器类。当一个类中有集合元素,且需要迭代访问时,可以在类中创建一个getIterator()方法用于获取和返回一个迭代器对象,之后该类就可以使用返回的迭代器访问类中的集合元素了。

中介者模式Mediator

用一个中介对象封装一些列对象的交互,使其耦合松散

主要用于解决多个同类对象间的通信复杂性问题。

类似于享元模式,不同点在于中介者模式中的对象容器,可以由参与者动态添加或删除。一个参与者信息的变动,可以通过中介者类中的容器,广播给其他参与者

观察者模式Observer

定义对象间的一种一对多关系,当一个对象状态改变时,所有依赖它的对象都会得到通知

也叫发布订阅模式。类似于中介这模式,不同点在于参与者的不同。观察者模式中的参与者不再是同类的对象,而是分为订阅者和发布者。订阅者可以对观察者类中的对象容器进行操作,即订阅和取消订阅。发布者则只能使用观察者类中的发布方法,向订阅者发布消息

备忘录模式Memento

在不破坏对象封装性的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。在需要时可以将对象恢复到原先保存的状态。

也叫做快照模式,和原型模式有些类似,都是在类内部对自己的属性进行克隆操作。

不同点在于,备忘录模式中,文档类对自身属性的克隆时机不需要放在clone方法中,而是在类的某些信息发生变动时。生成的克隆对象叫做备忘录对象,这些对象需要实现一个备忘录接口,接口方法是一些对信息的读取和操作。生成备忘录对象后,需要把这些备忘录对象以栈的形式存储。当文档类进行快照读取时,从栈中依次取出备忘录对象,然后使用备忘录对象的方法读取备忘录数据。

状态模式State

允许一个对象在其内部状态改变时改变它的行为

其实就是工厂模式的实际应用。工厂模式中,最终结果是根据条件实例化一个类。状态模式是把生成的类传入使用的方法中,使用方法根据传入的类(即状态)不同,执行不同的工作。

策略模式Strategy

定义一系列算法把它们一个个封装起来,并且使它们可以互相替换

就是状态模式的另外一种称呼。这两个模式只是在概念的理解上稍有不同,状态模式强调的是结果的不同,策略模式强调的是过程的不同。

访问者模式Visitor

相当于升级版本的策略模式。策略模式中,根据条件变换单个调用对象,以改变原有代码的运行结果。访问者模式则是根据条件,变更访问者对象(访问者对象中包含多个调用对象),来改变代码的运行结果。以下是访问者模式类图

ElementA、B、C属于被调用对象,被调用对象中除了自身的业务方法外,都要实现一个accept方法,用于接收访问者对象,并调用访问者对象中针对该对象的方法。

访问者对象,针对每一个被调用对象都要实现一个访问方法,用于将传入的调用对象赋值给当前的访问者对象。访问者可以把接收后的调用对象就行各种扩展

客户端调用时,实例化被调用对象,然后调用accept方法把对象传入访问者。之后就可以通过访问者调用被调用对象的各个方法。更换访问者对象后,就可以实现功能的切换

模板模式Template(类)

定义一个算法骨架,将一些步骤延迟到子类中。使得子类可以不改变一个算法结果即可重定义算法的某些特定步骤

用以解决执行顺序确定,但顺序中每个节点功能不确定的问题。

比如盖房子,标准顺序是打地基、建围墙、封顶、安门窗、走水电、室内装修。盖房子时必须严格按照此顺序执行,但是各个阶段可能因为房子的不同导致工艺、材质有所不同。

这个时候我们把每个步骤抽象出来,但是房子建造的顺序在父类中实现。每个子类可以自由实现各个步骤,但是建造顺序必须继承父类。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【山西长治】《长治市市直部门政务信息化建设项目预算编制规范和预算编制标准》(长财行[2022]25号)-省市费用标准解读系列32

《长治市市直部门政务信息化建设项目预算编制规范和预算编制标准(试行)》(长财行[2022]25号)于2022年8月1日开始试行,此标准由长治市财政局、长治市行政审批管理局编制,是对信息化建设项目预算管理的基本要求,主要适用…

Docker 入门:如何使用 Docker 容器化 AI 项目(二)

四、将 AI 项目容器化:示例实践 - 完整的图像分类与 API 服务 让我们通过一个更完整的 AI 项目示例,展示如何将 AI 项目容器化。我们以一个基于 TensorFlow 的图像分类模型为例,演示如何将训练、推理、以及 API 服务过程容器化。 4.1 创建 …

Java和Go语言的优劣势对比

文章目录 Java和Go语言的优劣势对比一、引言二、设计哲学与语法特性1、设计哲学2、语法特性 三、性能与内存管理1、性能2、内存管理和垃圾回收 四、并发编程模型五、使用示例1、Go语言示例代码2、Java语言示例代码 六、对比表格七、总结 Java和Go语言的优劣势对比 一、引言 在…

Docker怎么关闭容器开机自启,批量好几个容器一起操作?

环境: WSL2 docker v25 问题描述: Docker怎么关闭容器开机自启,批量好几个容器一起操作? 解决方案: 在 Docker 中,您可以使用多种方法来关闭容器并配置它们是否在系统启动时自动启动。以下是具体步骤和…

Pytorch | 利用BIM/I-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击

Pytorch | 利用BIM/I-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击 CIFAR数据集BIM介绍基本原理算法流程 BIM代码实现BIM算法实现攻击效果 代码汇总bim.pytrain.pyadvtest.py 之前已经针对CIFAR10训练了多种分类器: Pytorch | 从零构建AlexNet对CIFAR10进行分类 Py…

网狐旗舰版源码搭建概览

简单的列一下: 服务端源码内核源码移动端源码核心移动端源码AI控制工具源码多款子游戏源码前端、管理后台、代理网站源码数据库自建脚本UI工程源码配置工具及二次开发帮助文档 编译环境要求 VS2015 和 Cocos3.10 环境,支持移动端 Android 一键编译&am…

【QT】:QT(介绍、下载安装、认识 QT Creator)

背景 🚀 在我们的互联网中的核心岗位主要有以下几种 开发(程序员)测试运维(管理机器)产品经理(非技术岗位,提出需求) 而我们这里主要关注的是开发方向,开发岗位又分很…

MySQL 数据”丢失”事件之 binlog 解析应用

事件背景 客户反馈在晚间数据跑批后,查询相关表的数据时,发现该表的部分数据在数据库中不存在 从应用跑批的日志来看,跑批未报错,且可查到日志中明确显示当时那批数据已插入到数据库中 需要帮忙分析这批数据丢失的原因。 备注:考虑信息敏感性,以下分析场景测试环境模拟,相关数据…

熊军出席ACDU·中国行南京站,详解SQL管理之道

12月21日,2024 ACDU中国行在南京圆满收官,本次活动分为三个篇章——回顾历史、立足当下、展望未来,为线上线下与会观众呈现了一场跨越时空的技术盛宴,吸引了众多业内人士的关注。云和恩墨副总经理熊军出席此次活动并发表了主题演讲…

Spring01 - 工厂篇

Spring入门(上)-工厂篇 文章目录 Spring入门(上)-工厂篇一:引言1:EJB存在的问题2:什么是Spring3:设计模式和反射工厂 二:第一个spring程序1:环境搭建2:核心API - ApplicationContext2.1&#xf…

攻防世界 unserialize3

开启场景 题目为unserialize3,这个单词在php中代表反序列化,代码 __wakeup 也是php反序列化中常见的魔术方法,所以这个题基本就是和反序列化有关的题目。根据代码提示,编写一个Exploit运行,将对象xctf的信息序列化 得到…

汽车免拆诊断案例 | 2011 款奔驰 S400L HYBRID 车发动机故障灯异常点亮

故障现象 一辆2011款奔驰 S400L HYBRID 车,搭载272 974发动机和126 V高压电网系统,累计行驶里程约为29万km。车主反映,行驶中发动机故障灯异常点亮。 故障诊断 接车后试车,组合仪表上的发动机故障灯长亮;用故障检测…

GitLab安装及使用

目录 一、安装 1.创建一个目录用来放rpm包 2.检查防火墙状态 3.安装下载好的rpm包 4.修改配置文件 5.重新加载配置 6.查看版本 7.查看服务器状态 8.重启服务器 9.输网址 二、GitLab的使用 1.创建空白项目 2.配置ssh 首先生成公钥: 查看公钥 把上面的…

Electron 学习笔记

目录 一、安装和启动electron 1. 官网链接 2. 根据文档在控制台输入 3. 打包必填 4. 安装electron开发依赖 5. 在开发的情况下打开应用 6. 修改main为main.js,然后创建main.js 7.启动 二、启动一个窗口 1. main.js 2. index.html 3. 隐藏菜单栏 三、其他…

网络管理-期末项目(附源码)

环境:网络管理 主机资源监控系统项目搭建 (保姆级教程 建议点赞 收藏)_搭建网络版信息管理系统-CSDN博客 效果图 下面3个文件的项目目录(python3.8.8的虚拟环境) D:\py_siqintu\myproject5\Scripts\mytest.py D:\py_siqintu\myproject5\Sc…

62.基于SpringBoot + Vue实现的前后端分离-驾校预约学习系统(项目+论文)

项目介绍 伴随着信息技术与互联网技术的不断发展,人们进到了一个新的信息化时代,传统管理技术性没法高效率、容易地管理信息内容。为了实现时代的发展必须,提升管理高效率,各种各样管理管理体系应时而生,各个领域陆续进…

MySQL用表组织数据

用表组织数据 文章目录 用表组织数据一.四种完整性约束二.数值类型2-1三.数值类型2-2四.字符串.日期类型五.设置1.设置主键2.设置标识列3.设置非空4.设置默认值 六.主外键建立后注意事项 一.四种完整性约束 1.域完整性 列 域完整性约束方法:限制数据类型,检查约束,外键约束,默…

iOS开发代码块-OC版

iOS开发代码块-OC版 资源分享资源使用详情Xcode自带代码块自定义代码块 资源分享 自提: 通过网盘分享的文件:CodeSnippets 2.zip 链接: https://pan.baidu.com/s/1Yh8q9PbyeNpuYpasG4IiVg?pwddn1i 提取码: dn1i Xcode中的代码片段默认放在下面的目录中…

基于微信小程序的校园访客登记系统

基于微信小程序的校园访客登记系统 功能列表 用户端功能 注册与登录 :支持用户通过手机号短信验证码注册和登录。个人资料管理 :允许用户编辑和更新个人信息及其密码。站内信消息通知:通知公告。来访预约:提交来访预约支持车牌…

mac启ssh服务用于快速文件传输

x.1 在mac上启SSH服务 方法一:图形交互界面启ssh(推荐) 通过sharing - advanced - remote login来启动ssh;(中文版mac应该是 “系统设置 → 通用 → 共享”里打开“远程登录”来启动) 查看自己的用户名和…