软件常见设计模式

news2024/9/22 22:42:15

设计模式

设计模式是为了解决在软件开发过程中遇到的某些问题而形成的思想。同一场景有多种设计模式可以应用,不同的模式有各自的优缺点,开发者可以基于自身需求选择合适的设计模式,去解决相应的工程难题。

良好的软件设计和架构,可以让代码具备良好的可读性、可维护性、可扩展性、可复用性,让整个系统具备较强的鲁棒性和性能,减少屎山代码出现的概率。


创建型模式

创建型设计模式提供了各种对象创建机制,增加了现有代码的灵活性和重用性。

工厂方法模式(Factory Method):为超类提供了一个创建对象的接口,但允许子类改变将被创建的对象的类型。

优点:

  • 良好的封装性。将产品的实例化封装执行,避免被修改,这样的产品具备良好的一致性。
  • 良好的扩展性。增加产品时,同步增加一个工厂子类,不会违反开闭原则。
  • 标准的解耦合框架。使用者只需要知道自己要什么产品即可,不用去管产品具体的特性等等,降低了模块间的耦合。

缺点:

  • 代码量大。每加一个产品,都要加一个工厂子类,代码会显得臃肿。
  • 不利于扩展复杂的产品结构。


抽象工厂模式(Abstract Factory):允许您在不指定具体类的情况下生成一组相关对象的模式,相当于升级版的工厂模式。

优点:

  • 具体类分离。具体产品类在具体工厂的实现中进行了分离和归类。
  • 易于更换产品族。当客户想要改变整个产品族时,只需要切换具体工厂即可。
  • 利于产品一致性。当产品族的各个产品需要在一起执行时,抽象工厂可以确保客户只操作同系列产品,而不会进行跨品牌的组合。

缺点:

  • 不利于添加新种类产品。每加一个新的种类,如多一个项链类型的产品,那每一个具体工厂都要进行代码的扩展,且破坏了原先规定的结构,违反了开闭原则。


建造者模式(Builder):允许您逐步构建复杂对象的模式。该模式允许您使用相同的构建代码生成不同类型和表示的对象。

优点:

  • 封装性好。有效地封装了建造过程(主要业务逻辑),使得系统整体的稳定性得到了一定保证。
  • 解耦。产品本身和建造过程解耦,相同的建造过程可以创建出不同的产品。
  • 产品建造过程精细化。该模式注重产品创建的整个过程,将复杂的步骤拆解得到多个相对简单的步骤,使得系统流程更清晰,且对细节的把控更精准。
  • 易于扩展。如果有新产品需求,只需要添加一个建造者类即可,不需要改动之前的代码,符合开闭原则。

缺点:

  • 产品的组成部分和构建过程要一致,限制了产品的多样性。
  • 若产品内部有结构上的变化,则整个系统都要进行大改,增加了后期维护成本。


原型模式(Prototype):允许您复制现有对象而不使您的代码依赖于它们的类的模式。

优点:

  • 便捷、简洁、高效。不需要考虑对象的复杂程度,只需要复制即可。
  • 无需初始化。可动态地获取当前原型的状态,并在当前基础上进行拷贝。
  • 允许动态增加或减少产品类。

缺点:

  • 每个类都需要配备一个clone函数,若对已有的类进行改造,需要修改其源码,违背了开闭原则。


单例模式(Singleton):单例模式是一种创建型的软件设计模式,在工程项目中非常常见。通过单例模式的设计,使得创建的类在当前进程中只有一个实例,并提供一个全局性的访问点,这样可以规避因频繁创建对象而导致的内存飙升情况。


结构型设计模式

结构型设计模式解释了如何将对象和类组合成更大的结构,同时保持这些结构的灵活性和高效性。

适配器模式(Adapter):允许具有不兼容接口的对象进行协作的模式。

优点:

  • 良好封装性。接口内的内容对使用者而言是透明的,即看不见,这确保了内部功能具备较好的封装性,不易被改动。
  • 解耦。不匹配的两方在适配器的作用下可以做到解耦,不需要修改任何一方原有代码逻辑。
  • 良好复用性。适配的两方不需要做任何修改,业务的实现可以通过适配器来完成,不同的业务可以使用不同的适配器。
  • 良好扩展性。若要增加业务场景,只需要增加适配器类,来满足业务即可。

缺点:

  • 不利于维护。因为业务的实现基于适配器完成,适配器中代码的复杂程度会越来越高,不熟悉业务或者底层逻辑的人难以短时间内接手维护。
  • 系统结构易混乱。当业务量快速增加时,适配器类的数量也会快速增加,没有良好的系统架构布局,最终会使得整个系统臃肿且危险。


桥接模式(Bridge):将一个大类或一组紧密相关的类分割成两个独立的层次结构(抽象和实现),使它们可以相互独立地进行开发的模式。

优点:

  • 扩展性好。抽象与实现分离,扩展起来更便捷,可以获得更多样式的目标。
  • 解耦。不同抽象间的耦合程度低。
  • 满足设计模式要求的合成复用原则和开闭原则。
  • 封装性好。具体实现细节对客户而言是透明不可见的。

缺点:

  • 使用场景有限制。只有系统有两个以上独立变化维度时才适用。


复合模式(Composite):将对象组合成树状结构,然后以与单个对象相同的方式处理这些结构的模式。

优点:

  1. 层次鲜明。凸显“部分-整体”的层次结构。
  2. 一致性。对叶子对象(单)和容器对象(组合)的操作具备良好一致性。
  3. 节点自由度高。在结构中按需自由添加节点。

缺点:

  1. 设计更抽象。
  2. 应用场景限制。


装饰器模式(Decorator):将具有特定行为的对象放置在包含这些行为的特殊包装对象中,从而使您可以向对象附加新的行为的模式。

优点:

  • 灵活性好。相比较继承,装饰模式扩展对象功能更加灵活。
  • 扩展性好。不同装饰组合,可以创造出各式各样的对象,且避免了类爆炸。
  • 满足设计模式要求的开闭原则和合成复用原则。
  • 透明性好。客户端针对抽象操作,对具体实现的内容不可见。

缺点:

  • 复杂性高。装饰模式的设计往往具备较高复杂度,对开发者的水平要求高。
     


外观模式(Facade):为库、框架或任何其他复杂的类集合提供简化的接口的模式。

优点:

  • 简洁易使用。为复杂的模块和系统提供了一个简单的接口,简易化操作。
  • 保证了子系统独立性。子系统间独立性良好,彼此间一般不受影响,如何使用由门面决定。
  • 保证了系统稳定性。当直接使用子系统,可能会出现无法预知的异常时,门面模式可通过高层接口规范子系统接口的调用,且有效阻隔子系统和客户端间的交互,进而增强系统鲁棒性。
  • 隐秘性好。门面将子系统的具体细节都封装了起来。

缺点:

  • 不符合开闭原则。添加新系统要对门面进行修改。
  • 对开发者要求高。开发者需要了解子系统间的业务逻辑关系,这样才能确保封装的高层接口是有效且稳定的。


享元模式(Flyweight):通过在多个对象之间共享状态的公共部分,而不是在每个对象中保留所有数据,可以将更多对象适应可用的内存量的模式。

优点:

  1. 减少资源浪费。共享资源极大程度降低了系统的资源消耗。
  2. 提高系统运行效率。当资源过度使用时,系统效率会大受影响。

缺点:

  1. 维护共享对象,需要额外开销。
  2. 系统复杂度提高。运行享元,除了内外状态,还有线程方面都要充分考虑。


代理模式(Proxy):提供另一个对象的替代或占位符的模式。代理控制对原始对象的访问,允许您在请求传递到原始对象之前或之后执行某些操作。

优点:

  • 职责清晰。真实对象专注于自身业务逻辑,不用考虑其他非本职内容,交给代理完成。
  • 高拓展性。真实对象的改变不影响代理。
  • 解耦。将客户端与真实对象分离,降低系统耦合度。
  • 提高性能。虚拟代理可以减少系统资源的消耗。
  • 高安全性和稳定性。代理能很好地控制访问,提高程序安全。

缺点:

  • 增加系统复杂度。代理的职责往往较冗杂。
  • 请求速度降低。客户端与真实对象中加入代理,一定程度上会降低整个系统流程的运行效率。

行为型设计模式

行为型设计模式关注算法和对象之间责任的分配。

责任链模式(Chain of Responsibility):允许你将请求沿着一条处理器链传递。每个处理器在接收到请求后决定是处理该请求还是将其传递给链中的下一个处理器。

优点:

  • 请求者和接收者松耦合。请求者只需要发送请求,不关心由谁处理怎么处理;接收者只需要处理自己该处理的,剩下的交给责任链上的其他职责处理。
  • 比较灵活。责任链上各个职责对象,可以灵活排序或组合,以应对不同场景。

缺点:

  • 性能易受影响。当责任链过长时,对请求的处理效率不够高。
  • 不一定确保请求完整处理。每个职责只对自身部分负责,有可能请求走完整个责任链,也没有完全处理。


命令模式(Command):将请求转换为独立的对象,该对象包含有关请求的所有信息。通过这种转换,您可以将请求作为方法参数传递、延迟或排队请求的执行,并支持可撤销的操作。


迭代器模式(Iterator):让您遍历集合的元素,而不暴露其底层表示(如列表、堆栈、树等)。

优点:

  • 符合单一职责原则。将遍历行为抽离成单独的类。
  • 符合开闭原则。添加新集合或者新迭代器,不改变原有代码。
  • 便于扩展多种遍历行为。
  • 访问数据又不暴露内部。

缺点:

  • 若对聚合对象只需要进行简单的遍历行为,那使用迭代器模式有些大材小用。
  • 系统复杂性提高,类数量较多。


中介者模式(Mediator):减少对象之间混乱的依赖关系。该模式限制了对象之间的直接通信,并强制它们只能通过中介者对象进行协作。


备忘录模式(Memento):在不透露其实现细节的情况下,保存和恢复对象的先前状态。

优点:

  • 良好封装性。发起人对象中的内部状态被保存在备忘录中,也只能由自己读取,对其他对象起到了屏蔽作用。
  • 提供了状态恢复机制。类似于游戏存档读档。
  • 简化了发起人职责。发起人状态的存储和获取,被分离出去了。

缺点:

  • 资源消耗较大,对发起人对象不同内部状态的存储,会导致开销增加。


观察者模式(Observer):定义订阅机制,以通知多个观察对象有关它们所观察的对象发生的任何事件。


状态模式(State):当对象的内部状态发生变化时,允许对象改变其行为。它看起来就像对象改变了它的类。


策略模式(Strategy):定义一族算法,将每个算法都封装在独立的类中,并使它们的对象可互换使用。


模板方法模式(Template Method):在超类中定义算法的骨架,但允许子类在不改变其结构的情况下覆盖特定的步骤。

优点:

  • 良好复用性。父类中公共部分可以多次使用,具备好的环境适应性。
  • 良好扩展性。子类对父类模板的具体实现作扩展。
  • 符合开闭原则。基于模板扩展功能,不需要改动原有代码。

缺点:

  • 类个数增加。基于模板的每个实现,都要定义一个子类,容易使代码量膨胀。
  • 若父类模板有改动,则子类均要同步更改。


访问者模式(Visitor):将算法与其操作的对象分离开来。

优点:

  • 良好扩展性。扩展对元素的操作,只需要添加访问者。
  • 满足单一职责原则。相关的操作封装为一个访问者,使得访问者职责单一。
  • 解耦。数据结构自身和作用于它的操作解耦合。

缺点:

  • 不易增加元素类。每增加一个元素类,访问者的接口和实现都要进行变化。
  • 违背了依赖倒置原则。访问者依赖的是具体元素而不是抽象元素。
  • 破坏封装。访问者可以获取被访问元素的细节。

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

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

相关文章

不要抱怨,不如抱 Java 运算符吧 (1)

本篇会加入个人的所谓‘鱼式疯言’ ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. 🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人…

LLMChain使用 | RouterChain的使用 - 用本地大模型搭建多Agents

单个本地大模型搭建参考博客 单个Chain:面对一个需求,我们需要创建一个llmchain,设置一个prompt模板,这个chain能够接收一个用户input,并输出一个结果;多个Chain:考虑到同时面对多个需求&#x…

十六、多边形填充和绘制

项目功能实现&#xff1a;对多边形进行轮廓绘制和填充 按照之前的博文结构来&#xff0c;这里就不在赘述了 一、头文件 mult-drawing.h #pragma once#include<opencv2/opencv.hpp>using namespace cv;class Mult_Drawing { public:void mult_drawing(); };#pragma onc…

Employee Management系统存在Sql注入 附源代码

免责声明&#xff1a;本文所涉及的信息安全技术知识仅供参考和学习之用&#xff0c;并不构成任何明示或暗示的保证。读者在使用本文提供的信息时&#xff0c;应自行判断其适用性&#xff0c;并承担由此产生的一切风险和责任。本文作者对于读者基于本文内容所做出的任何行为或决…

C++日志库plog使用指南

前言 之前介绍过一个C语言日志库 轻量级c语言开源日志库log.c介绍&#xff0c;源代码只有不到200行&#xff0c;使用非常方便。但是也存在很多缺点&#xff0c;比如日志时间只支持打印到秒&#xff0c;没有作多线程处理&#xff0c;不支持日志回滚。在小型项目或者测试demo中使…

如何将cocos2d-x js打包部署到ios上 Mac M1系统

项目环境 cocos2d-x 3.13 xcode 12 mac m1 big sur 先找到你的项目 使用xcode软件打开上面这个文件 打开后应该是这个样子 执行编译运行就好了 可能会碰到的错误 在xcode11版本以上都会有这个错误&#xff0c;这是因为iOS11废弃了system。 将上面代码修改为 #if (CC_TARGE…

打败茅台的“老酒”

作者&#xff1a;翻篇 琥珀酒研社快评&#xff1a; 最可恨的 从来不是什么强大敌人 而是美名其曰的猪队友 要不怎么有网友说 酒鬼酒太惨了 当年要不是败给内鬼 又曝出塑化剂事件 错过白酒发展的黄金十年 不说打败茅台、五粮液 但成为另一个茅台、五粮液 那完全有希…

【智慧零售】门店管理设备解决方案,为企业数字化运营升级赋能

2023年我国零售总额超47万亿元&#xff0c;广阔的市场提供了更多机遇&#xff0c;同时随着日趋激烈的竞争&#xff0c;企业也正面临着一些挑战&#xff1a;如何才能有效提升门店生产效率&#xff1f;降低门店运营成本&#xff1f;提高市场竞争力&#xff1f; 零售企业认识到通…

Vue3 + Ts (使用lodash)

安装 npm i --save lodash使用 import _ from lodash⚠️报警告&#xff1a;&#xff01;&#xff01;&#xff01; 此时还需要安装ts声明文件库 npm install types/lodash -D安装之后重启Vscode还是会提示上面的警告&#xff0c;此时还需在tsconfig.ts里面配置 {"c…

QT day2 2.21

1.使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 代码&#xff1a; #include "mywidget.h" #include "ui_mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(pa…

C语言文件操作学习【2】—— 文件的顺序读写

顺序读写函数介绍 函数名功能适用于fgetc字符输入函数所有输入流fputc字符输出函数所有输出流fgets文本行输入函数所有输入流fputs文本行输出函数所有输出流fscanf格式化输入函数所有输入流fprintf格式化输出函数所有输出流fread二进制输入文件fwrite二进制输出文件 上面说的…

Cartographer框架简述

catographer框架分为前端和后端 前端包括雷达数据处理&#xff1b;位姿预测&#xff1b;扫描匹配和栅格地图更新。 后端包括后端&#xff1a;线程池任务与调度&#xff1b;向位姿图添加节点&#xff0c;计算节点的子图内约束和子图间约束&#xff08;回环检测&#xff09;&…

HAL STM32 HW I2C DMA + SSD1306/SH1106驱动示例

HAL STM32 HW I2C DMA SSD1306/SH1106驱动示例 &#x1f4cd;硬件I2C DMA驱动参考&#xff1a;https://blog.csdn.net/weixin_45065888/article/details/118225993 &#x1f4cc;github上的相关项目&#xff1a;https://github.com/taburyak/STM32_OLED_SSD1306_HAL_DMA &am…

typescript映射类型

ts映射类型简介 TypeScript中的映射类型&#xff08;Mapped Type&#xff09;是一种高级类型&#xff0c;它允许我们基于现有类型创建新的类型&#xff0c;同时对新类型的每个属性应用一个转换函数。通过使用映射类型&#xff0c;我们可以方便地对对象的属性进行批量操作&…

猫头虎分享已解决Bug || 系统更新失败(System Update Failure):UpdateError, UpgradeFailure

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

nginx详细教程

一、nginx简介 1. 概述 Nginx 是一款轻量级的 Web 服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器&#xff0c;在 BSD-like 协议下发行。其特点是占有内存少&#xff0c;并发能力强&#xff0c;事实上 nginx 的并发能力在同类型的网页服务器中…

VMware连通问题

虚拟机配好后发现竟然到网关都不通做了一系列排查后 最后在真机上查看发现VMware的NAT服务没有开启 WinR输入services.msc&#xff0c;启动VMware NAT Service后问题就解决了&#xff01;

【软件架构】02-复杂度来源

1、性能 1&#xff09;单机 受限于主机的CPU、网络、磁盘读写速度等影响 在多线程的互斥性、并发中的同步数据状态等&#xff1b; 扩展&#xff1a;硬件资源、增大线程池 2&#xff09;集群 微服务化拆分&#xff0c;导致调用链过长&#xff0c;网络传输的消耗过多。 集…

L2 清点代码库----PTA(疑问)

上图转自新浪微博&#xff1a;“阿里代码库有几亿行代码&#xff0c;但其中有很多功能重复的代码&#xff0c;比如单单快排就被重写了几百遍。请设计一个程序&#xff0c;能够将代码库中所有功能重复的代码找出。各位大佬有啥想法&#xff0c;我当时就懵了&#xff0c;然后就挂…

基于SpringBoot+MyBatis-Plus的教务管理系统

基于SpringBootMyBatis-Plus的教务管理系统 教务管理系统开发技术功能模块代码结构数据库设计运行截图源码获取 教务管理系统 欢迎访问此博客&#xff0c;是否为自己的毕业设计而担忧呢&#xff1f;是否感觉自己的时间不够做毕业设计呢&#xff1f;那你不妨看一下下面的文章&a…