软件常见设计模式

设计模式

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

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


创建型模式

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

工厂方法模式(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.mzph.cn/news/700680.shtml

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

相关文章

k8s的svc流量通过iptables和ipvs转发到pod的流程解析

文章目录 1. k8s的svc流量转发1.1 service 说明1.2 endpoints说明1.3 pod 说明1.4 svc流量转发的主要工作 2. iptables规则解析2.1 svc涉及的iptables链流程说明2.2 svc涉及的iptables规则实例2.2.1 KUBE-SERVICES规则链2.2.2 KUBE-SVC-EFPSQH5654KMWHJ5规则链2.2.3 KUBE-SEP-L…

css复习

盒模型相关: border:1px solid red (没有顺序) 单元格的border会发生重叠,如果不想要重叠设置 border-collapse:collapse (表示相邻边框合并在一起) padding padding影响盒子大小的好处使用 margin应用: 行内或行内块元素水…

windows Server下Let‘s Encrypt的SSL证书续期

一、手动续期方法: 暂停IIS服务器 --> 暂时关闭防火墙 --> 执行certbot renew --> 打开防火墙 --> 用OpenSSL将证书转换为PFX格式-->pfx文件导入到IIS --> IIS对应网站中绑定新证书 --> 重新启动IIS -->完成 1、暂停IIS服务器 2、暂时关闭…

【LeetCode每日一题】 单调栈的案例 42. 接雨水

这道题是困难,但是可以使用单调栈,非常简洁通俗。 关于单调栈可以参考单调栈总结以及Leetcode案例解读与复盘 42. 接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例 …

浅析SpringBoot框架常见未授权访问漏洞

文章目录 前言Swagger未授权访问RESTful API 设计风格swagger-ui 未授权访问swagger 接口批量探测 Springboot Actuator未授权访问数据利用未授权访问防御手段漏洞自动化检测工具 CVE-2022-22947 RCE漏洞原理分析与复现漏洞自动化利用工具 其他常见未授权访问Druid未授权访问漏…

私域运营-需要认清的事实

一、私域不能单纯依靠微信渠道 误区:很多企业仍停留在如何让用户在微信去分享裂变,然后带动新用户的阶段。 私域的核心在于“开源节流”,就是如何通过更多渠道获取更多客户,并且避免客户的批量流失。 私域讲究的是如何从公域的“…

【读博杂记】:近期日常240223

近期日常 最近莫名其妙,小导悄悄卷起来,说要早上八点半开始打卡,我感觉这是要针对我们在学校住的,想让我们自己妥协来这边租房子住,但我感觉这是在逼我养成规律作息啊!现在基本上就是6~7点撤退,…

Ubuntu20.04开启/禁用ipv6

文章目录 Ubuntu20.04开启/禁用ipv61.ipv62. 开启ipv6step1. 编辑sysctl.confstep2. 编辑网络接口配置文件 3. 禁用ipv6(sysctl)4. 禁用ipv6(grub)附:总结linux网络配置 Ubuntu20.04开启/禁用ipv6 1.ipv6 IP 是互联网…

openGauss学习笔记-227 openGauss性能调优-系统调优-其他因素对LLVM性能的影响

文章目录 openGauss学习笔记-227 openGauss性能调优-系统调优-其他因素对LLVM性能的影响 openGauss学习笔记-227 openGauss性能调优-系统调优-其他因素对LLVM性能的影响 LLVM优化效果不仅依赖于数据库内部具体的实现,还与当前所选择的硬件环境等有关。 表达式调用C…

【力扣白嫖日记】176.第二高的薪水

前言 练习sql语句,所有题目来自于力扣(https://leetcode.cn/problemset/database/)的免费数据库练习题。终于把所有的简单题刷完,进入第一道中等题。 今日题目: 176.第二高的薪水 表:Employee 列名类型…

CSS 的圆角矩形

CSS 的圆角矩形 通过 border-radius 属性使矩形边框带圆角效果成为圆角矩形 语法:border-radius: length; length 是内切圆的半径,其数值越大, 弧线越明显 border-radius 属性值描述length定义圆角的形状%以百分比定义圆角的形状 生成圆形 让 border-…

村镇医院医疗中心污废水如何处理达标

污废水处理是村镇医院医疗中心运营中不可忽视的重要环节。如何有效处理污废水,使其达到相关标准,是保障医疗中心环境卫生的关键之一。 首先,村镇医院医疗中心应建立科学的废水处理系统。该系统应包括预处理、初级处理、中级处理和高级处理等环…

JVM(1)

JVM简介 JVM是Java Virtual Machine的简称,意为Java虚拟机. 在java中,它归属于jre(java运行时环境), 而jre归属于jdk(java开发工具包). 虚拟机是指通过软件模拟的具有完整硬件功能的,运行在一个完全隔离的环境中的完整计算机系统. 常见的虚拟机:JVM, VMwave, VirtualBox. J…

2024 Impeller:快速了解 Flutter 的渲染引擎的优势

参考原文 :https://tomicriedel.medium.com/understanding-impeller-a-deep-dive-into-flutters-rendering-engine-ba96db0c9614 最近,在 Flutter 2024 路线规划里明确提出了,今年 Flutter Team 将计划删除 iOS 上的 Skia 的支持,…

python 打包 apk

转换之前python代码需要使用指定的框架才能转换,列如:kivy from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Buttonimport time import pyautogui import threadingstatus False# 这是一个将被线程执…

踩坑:SpringBoot连接Mysql的时区报错

解决方法:1.修改时区2.修改连接版本 目录 1.修改时区 2.切换版本 1.修改时区 查看mysql的默认时区 SELECT global.time_zone AS Global Time Zone, session.time_zone AS Session Time Zone; 查看mysqk的默认是时区返回两个结果 Global Time Zone:表示Mysql…

【数据结构】C语言实现二叉树的相关操作

树 定义 树(Tree)是 n (n > 0) 个结点的有限集 若 n 0,称为空树 若 n > 0,则它满足如下两个条件: 有且仅有一个特定的称为根(Root)的结点其余结点可分为 m(m>0) 个互不相交的有限…

剪辑视频调色怎么让画质变得清晰 视频剪辑调色技巧有哪些方面 剪辑视频免费的软件有哪些 会声会影调色在哪里 会声会影模板素材

视频调色的作用有很多,除了进行风格化剪辑以外,还可以让作品的画质变得清晰。通过调色来增强画面的清晰度,在观感上也会显得十分自然。视频调色的技巧有很多,并且原理大都十分简单。有关剪辑视频调色怎么让画质变得清晰&#xff0…

Mybatis总结--传参二

#叫做占位符 Mybatis是封装的JDBC 增强版 内部还是用的jdbc 每遇到一个#号 这里就会变为?占位符 一个#{}就是对应一个问号 一个占位符 用这个对象执行sql语句没有sql注入的风险 八、多个参数-使用Param 当 Dao 接口方法有多个参数,需要通过名称使…

Vue3_基础使用_4_路由器Router

概念: 路由:是一个key-value的对应关系叫路由。 路由器:管理多个路由的集合或者叫设备称为路由器。 由于现在组件替代了以前的mvc中的cshtml, 组件的菜单切换也不用我手动去写,vue给我们通过配置完成。 实现简单的路由跳转&…