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

【设计模式入门】设计模式全解析:23种经典模式介绍与评级指南(设计师必备)

文章目录

  • 设计模式简介
    • 引言
    • 七项基本原则
    • 创建型模式
      • 单例模式(Singleton)
      • 工厂方法模式(Factory Method)
      • 抽象工厂模式(Abstract Factory)
      • 建造者模式(Builder)
      • 原型模式(Prototype)
    • 结构型模式
      • 适配器模式(Adapter)
      • 桥接模式(Bridge)
      • 组合模式(Composite)
      • 装饰器模式(Decorator)
      • 外观模式(Facade)
      • 享元模式(Flyweight)
      • 代理模式(Proxy)
    • 行为型模式
      • 策略模式(Strategy)
      • 模板方法模式(Template Method)
      • 观察者模式(Observer)
      • 命令模式(Command)
      • 迭代器模式(Iterator)
      • 解释器模式(Interpreter)
      • 中介者模式(Mediator)
      • 备忘录模式(Memento)
      • 状态模式(State)
      • 访问者模式(Visitor)
    • 结语
      • 说明

设计模式简介

在这里插入图片描述

引言

设计模式是在软件工程领域中解决常见问题的有效方法。这些模式并不是具体的代码,而是一种通用的解决方案模板,可以帮助开发者在面对相似问题时能够快速地找到解决办法。设计模式通常被分为三大类:创建型、结构型和行为型。

七项基本原则

设计模式遵循若干基本原则,这些原则有助于指导软件设计,提高代码质量和可维护性。以下是设计模式中常用的几大原则:

  1. 单一职责原则(Single Responsibility Principle, SRP)
  • 一个类应该只有一个引起它变化的原因。
  • 通过将类的责任分离到不同的类中,可以提高模块的内聚性和降低模块间的耦合度。
  1. 开放封闭原则(Open/Closed Principle, OCP)
  • 软件实体(类、模块、函数等)应该是可以扩展的,但是不可以修改。
  • 通过继承和多态来实现扩展,而不是通过修改现有代码。
  1. 里氏替换原则(Liskov Substitution Principle, LSP)
  • 子类必须能够替换它们的基类。
  • 任何基类可以出现的地方,子类也一定可以出现。
  1. 依赖倒置原则(Dependency Inversion Principle, DIP)
  • 高层模块不应该依赖于低层模块,二者都应该依赖于抽象。
  • 抽象不应该依赖于细节,细节应该依赖于抽象。
  1. 接口隔离原则(Interface Segregation Principle, ISP)
  • 不应该强迫客户端依赖于它不需要的接口。
  • 客户端不应该被迫依赖于它们不使用的接口。
  1. 迪米特法则(Law of Demeter, LoD)
  • 一个对象应该对其他对象有尽可能少的了解。
  • 也称为最少知识原则,提倡减少对象间的相互作用。
  1. 合成复用原则(Composite Reuse Principle, CRP)
  • 尽量使用对象组合,而不是通过继承来达到复用的目的。

这些原则有助于指导开发者编写更加灵活、可扩展和易于维护的代码。在实际应用设计模式时,这些原则可以作为设计决策的重要依据。

创建型模式

创建型模式关注的是对象的创建方式,它们试图找出一个系统化的方法来创建对象,以便使得系统更加灵活。以下是几种典型的创建型模式及其简单介绍和应用场景。

单例模式(Singleton)

  • 简介:确保一个类只有一个实例,并提供一个全局访问点。
  • 应用场景
    • 当需要频繁地创建和销毁一个对象时,使用单例模式可以减少资源消耗。
    • 需要控制资源访问点的情况,例如数据库连接池、日志对象等。
  • 推荐阅读:
    【单例设计模式】揭秘单例模式:从原理到实战的全方位解析(开发者必读)

工厂方法模式(Factory Method)

  • 简介:定义一个创建对象的接口,但允许子类决定实例化哪一个类。
  • 应用场景
    • 当一个类不知道它所必须创建的对象的类的时候。
    • 类确定仅有一个实例需要被创建时,或者希望由子类来指定具体的类时。
  • 推荐阅读:
    【工厂方法模式】深度解析:从原理到实战的全方位指南(开发者必备)

抽象工厂模式(Abstract Factory)

  • 简介:提供一个接口,用于创建相关或依赖对象的家族,而无需指定它们具体的类。
  • 应用场景
    • 需要创建一组相关或相互依赖的对象,但具体类别不确定时。
    • 一个系统要独立于它的产品创建、组合时。
  • 推荐阅读:
    【抽象工厂模式】从理论到实战:构建可扩展的软件家族(设计模式系列)

建造者模式(Builder)

  • 简介:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
  • 应用场景
    • 如果创建复杂对象的算法应该独立于部件的组成部分以及它们的装配方式时。
    • 当对象的构建过程变得复杂,并且需要精细控制创建过程时。

原型模式(Prototype)

  • 简介:通过复制现有对象来创建新对象,而不是通过构造函数实例化。
  • 应用场景
    • 当创建对象的代价比较大时,可以通过复制现有的对象来创建新的对象。
    • 需要动态地获取对象的类信息或者构造函数的信息时。

结构型模式

结构型模式关注于如何组合类或对象以获得新的功能。以下是几种典型的结构型模式及其简单介绍和应用场景。

适配器模式(Adapter)

  • 简介:允许不兼容的接口之间可以协同工作。
  • 应用场景
    • 需要复用一些已有的类,但是接口又与当前系统不兼容时。
    • 想要创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(如那些来自第三方的类)协同工作。

桥接模式(Bridge)

  • 简介:将抽象部分与它的实现部分分离,使它们都可以独立变化。
  • 应用场景
    • 一个类的某些行为需要通过选择不同的实现来改变其表现。
    • 减少抽象和实现这两个可变维度的变化带来的组合爆炸问题。

组合模式(Composite)

  • 简介:将对象组合成树形结构以表示“整体-部分”的层次结构。
  • 应用场景
    • 你想表示对象的部分整体层次结构。
    • 你需要处理同一类型的对象集合,希望客户端不必关心单个对象还是对象组合。

装饰器模式(Decorator)

  • 简介:动态地给一个对象添加一些额外的职责。
  • 应用场景
    • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
    • 当不能采用继承的方法进行扩充时。

外观模式(Facade)

  • 简介:为子系统中的一组接口提供一个一致的界面,简化了客户端与系统的交互。
  • 应用场景
    • 客户端不需要知道子系统的细节,只需要一个简单的接口。
    • 当一个系统有多个子系统,每个子系统都有自己的接口,需要一个统一的接口来简化外部调用。

享元模式(Flyweight)

  • 简介:运用共享技术有效地支持大量细粒度的对象。
  • 应用场景
    • 一个应用系统有大量的细粒度对象。
    • 使用共享技术有助于减少内存中的对象数量。

代理模式(Proxy)

  • 简介:为其他对象提供一个代理以控制对这个对象的访问。
  • 应用场景
    • 在访问一个对象时执行一些附加操作,比如缓存、日志记录、权限检查等。
    • 控制对远程对象的访问,或者当直接访问对象开销过大时。

行为型模式

行为型模式关注于对象之间的职责分配以及通信机制。以下是几种典型的结构型模式及其简单介绍和应用场景。

策略模式(Strategy)

  • 简介:定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。
  • 应用场景
    • 当一个系统应该动态地在几种算法中选择一种时。
    • 算法的实现细节不应该影响客户端。

模板方法模式(Template Method)

  • 简介:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。
  • 应用场景
    • 一次性写出基本的算法框架,而将算法的具体步骤留给子类去实现。
    • 各个子类中公共的行为可以从父类中得到。

观察者模式(Observer)

  • 简介:当对象状态改变时通知所有依赖它的对象。
  • 应用场景
    • 当一个对象状态发生改变时,所有的依赖对象都需要得到通知并自动更新。
    • 实现事件监听器、发布订阅模式等。

命令模式(Command)

  • 简介:将一个请求封装为一个对象,从而使用户可用不同的请求对客户端进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
  • 应用场景
    • 将请求封装为对象后,可以方便地实现撤销/重做、事务等机制。
    • 当需要在不同的时刻指定请求、将请求排队、传递请求、执行请求时。

迭代器模式(Iterator)

  • 简介:提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
  • 应用场景
    • 遍历集合时,不需要暴露集合的内部结构。
    • 支持多种遍历方式。

解释器模式(Interpreter)

  • 简介:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
  • 应用场景
    • 当有一个语言需要解释执行,并且可将该语言中的句子表示为一个抽象语法树时。
    • 如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题定义为一种语言,并开发一个解释器来解释该语言。

中介者模式(Mediator)

  • 简介:用一个中介对象来封装一系列的对象交互。
  • 应用场景
    • 当一组对象以定义良好但是复杂的方式进行通信时,产生的相互依赖关系结构混乱且难以理解。
    • 当对象之间存在复杂的引用时,为了降低类之间的耦合。

备忘录模式(Memento)

  • 简介:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后恢复它。
  • 应用场景
    • 需要保存和恢复数据的相关状态(如游戏存档),但不能让其他对象访问其状态。
    • 需要为用户提供撤销功能。

状态模式(State)

  • 简介:允许一个对象在其内部状态改变时改变它的行为。
  • 应用场景
    • 对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为。
    • 控制对象的行为受到它所处状态的影响,并且代码必须因此与各个状态条件相关联。

访问者模式(Visitor)

  • 简介:主要将数据结构与数据操作分离。
  • 应用场景
    • 一个对象结构包含很多类对象,它们有不同的操作需要被执行,而且这些操作依赖这些对象的类。
    • 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而我们需要避免让这些操作“污染”这些对象的类。

结语

设计模式是软件开发中非常重要的概念,它们为开发者提供了解决问题的思路和经验。熟练掌握这些模式能帮助开发者编写出更灵活、更易于维护的代码。当然,这只是一个简短的介绍,每种模式背后都有着更为丰富的细节和技术要点,值得进一步探索。

下面是一个基于学习难度和使用频率两个维度来评估设计模式的表格。学习难度和使用频率都用星号来表示等级,其中星号越多表示等级越高。需要注意的是,这些等级是主观评估的结果,可能会因人而异。以下是23种设计模式的学习难度和使用频率等级:

设计模式学习难度使用频率
单例模式★★★★★★
工厂方法模式★★★★★
抽象工厂模式★★★★★
建造者模式★★★★★
原型模式★★
适配器模式★★★★★
桥接模式★★★★★
组合模式★★★★★
装饰器模式★★★★★
外观模式★★★★★
享元模式★★★
代理模式★★★★★
策略模式★★★★★
模板方法模式★★★★★
观察者模式★★★★★★★
命令模式★★★★★
迭代器模式★★★★
解释器模式★★★★
中介者模式★★★★★
备忘录模式★★★
状态模式★★★★★
访问者模式★★★★

说明

  • 学习难度:

    • ★:非常容易理解和实现。
    • ★★:相对容易理解和实现。
    • ★★★:中等到较高难度,需要一定的编程经验和理解。
    • ★★★★:较难理解和实现,通常涉及到较为复杂的概念或架构。
  • 使用频率:

    • ★:很少使用,只在特定场景下适用。
    • ★★:偶尔使用,在特定条件下有用。
    • ★★★:经常使用,适用于多种场景。
    • ★★★★:非常常用,几乎每个项目都会用到。

请注意,这些等级是根据一般经验和实践给出的大致估计,并非严格的标准。实际应用中,这些模式的使用频率和学习难度可能会有所不同。


希望这篇文章能够为你提供一个好的起点!如果你想要深入了解每一种模式的具体实现和应用场景,我后面会为每种模式单独写一篇文章供大家参考和学习。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • volatile 关键字的使用
  • 贪心系列专题篇四
  • pikachu文件下载
  • 详解爬虫使用代理ip的几种方案
  • 【GCC】结合GPT4 延迟梯度学习:公式推导及理论分析
  • 学习记录(11):训练图片分类的算法
  • 【linux】企业级linux内核优化方案,助你构建出高效、稳定且安全的Linux系统环境
  • MySQL深分页和浅分页
  • JVM详解(个人学习笔记)
  • 基于FPGA的数字信号处理(18)--半加器和全加器
  • 嵌入式网络调试命令 ifconfig 介绍及使用方法
  • 【五大海内外高校支持】2024年数字经济与计算机科学国际学术会议(DECS2024)
  • 壁纸头像小程序uniapp版(附源码)
  • YOLOv8新版本支持实时检测Transformer(RT-DETR)、SAM分割一切
  • nginx 代理 mysql 连接
  • 2017-08-04 前端日报
  • Android框架之Volley
  • Angular 响应式表单之下拉框
  • ES10 特性的完整指南
  • Git学习与使用心得(1)—— 初始化
  • js作用域和this的理解
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • Vue 重置组件到初始状态
  • Wamp集成环境 添加PHP的新版本
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 力扣(LeetCode)56
  • 前端存储 - localStorage
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • 小程序01:wepy框架整合iview webapp UI
  • ​HTTP与HTTPS:网络通信的安全卫士
  • # Swust 12th acm 邀请赛# [ A ] A+B problem [题解]
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • (Redis使用系列) Springboot 使用Redis+Session实现Session共享 ,简单的单点登录 五
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (笔记)M1使用hombrew安装qemu
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (三)终结任务
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (四)图像的%2线性拉伸
  • (贪心 + 双指针) LeetCode 455. 分发饼干
  • (转载)虚函数剖析
  • **CI中自动类加载的用法总结
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .h头文件 .lib动态链接库文件 .dll 动态链接库
  • @Autowired和@Resource的区别
  • @Bean有哪些属性
  • @LoadBalanced 和 @RefreshScope 同时使用,负载均衡失效分析
  • @Mapper作用
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节
  • @Transactional 详解
  • [ Linux 长征路第二篇] 基本指令head,tail,date,cal,find,grep,zip,tar,bc,unname
  • [2669]2-2 Time类的定义
  • [AI Embedchain] 开始使用 - 全栈