【1024 | 程序员节】浅谈前端开发中常用的设计模式——适配器模式、工厂模式、单例模式等

news2024/11/20 23:22:26

前言

博主主页👉🏻蜡笔雏田学代码
专栏链接👉🏻【前端面试专栏】
今天学习前端面试题相关的知识!
感兴趣的小伙伴一起来看看吧~🤞

文章目录

  • 设计模式
    • 设计模式分类
  • 工厂模式
    • 什么是工厂模式
    • 工厂模式好处
  • 单例模式
    • 什么是单例
    • 哪些地方用到了单例模式
    • 单例优缺点
    • 单例创建方式
  • 开发的过程中你用到过哪些设计模式
    • 适配器模式
    • 单例模式
    • 代理模式
    • 订阅发布模式
    • 观察者模式
  • 什么是 MVVM?与 MVC 有什么区别?

在这里插入图片描述

设计模式

设计模式分类

  1. 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
  2. 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
  3. 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

工厂模式

什么是工厂模式

它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。实现了创建者和调用者分离,工厂模式分为简单工厂、工厂方法、抽象工厂模式。

工厂模式好处

  • 工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。
  • 利用工厂模式可以降低程序的耦合性,为后期的维护修改提供了很大的便利。
  • 将选择实现类、创建对象统一管理和控制,从而将调用者跟我们的实现类解耦。

单例模式

什么是单例

保证一个类只有一个实例,并且提供一个访问该全局访问点。

哪些地方用到了单例模式

  • 网站的计数器,一般也是采用单例模式实现,否则难以同步。
  • 应用程序的日志应用,一般都是单例模式实现,只有一个实例去操作才好,否则内容不好追加显示。
  • 多线程的线程池的设计一般也是采用单例模式,因为线程池要方便对池中的线程进行控制。
  • Windows的(任务管理器)就是很典型的单例模式,它不能打开俩个。
  • windows的(回收站)也是典型的单例应用。在整个系统运行过程中,回收站只维护一个实例。

单例优缺点

优点:

  1. 在单例模式中,活动的单例只有一个实例,对单例类的所有实例化得到的都是相同的一个实例,这样就防止其它对象对自己的实例化,确保所有的对象都访问一个实例。
  2. 单例模式具有一定的伸缩性,类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。
  3. 提供了对唯一实例的受控访问。
  4. 由于在系统内存中只存在一个对象,因此可以节约系统资源,当需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。
  5. 允许可变数目的实例。
  6. 避免对共享资源的多重占用。

缺点:

  1. 不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
  2. 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
  3. 单例类的职责过重,在一定程度上违背了"单一职责原则"。
  4. 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。

单例创建方式

主要使用懒汉和懒汉式

  1. 饿汉式:类初始化时,会立即加载该对象,线程天生安全,调用效率高。
  2. 懒汉式:类初始化时,不会初始化该对象,真正需要使用的时候才会创建该对象,具备懒加载功能。

开发的过程中你用到过哪些设计模式

设计模式的定义:在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案

设计模式是前人解决某个特定场景下对而总结出来的一些解决方案。可能刚开始接触编程还没有什么经验的时候,会感觉设计模式没那么好理解,这个也很正常。有些简单的设计模式我们有时候用到,不过没意识到也是存在的。
学习设计模式,可以让我们在处理问题的时候提供更多更快的解决思路。

适配器模式

这个是我们常使用的设计模式,也算最简单的设计模式之一,好处在于可以保持原有接口的数据结构不变动

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。

例子
适配器模式很好理解,假设我们和后端定义了一个接口数据结构为(可以理解为旧接口):

[
  {
    "label": "选择一",
    "value": 0
  },
  {
    "label": "选择二",
    "value": 1
  }
]

但是后端后面因为其他原因,需要定义返回的结构为(可以理解为新接口):

[
  {
    "label": "选择一",
    "text": 0
  },
  {
    "label": "选择二",
    "text": 1
  }
]

然后我们前端使用到后端接口有好几处,那么我可以把新的接口字段结构适配为老接口的,就不需要各处去修改字段,只要把源头的数据适配好就可以了。
当然上面的是非常简单的场景,也是经常用到的场景。或许你会认为后端处理不更好了,的确是这样更好,但是这个不是我们讨论的范围。

单例模式

单例模式,从字面意思也很好理解,就是实例化多次都只会有一个实例

有些场景实例化一次,可以达到缓存效果,可以减少内存占用。还有些场景就是必须只能实例化一次,否则实例化多次会覆盖之前的实例,导致出现 bug(这种场景比较少见)。
例子
实现弹框的一种做法是先创建好弹框, 然后使之隐藏, 这样的话会浪费部分不必要的 DOM 开销, 我们可以在需要弹框的时候再进行创建, 同时结合单例模式实现只有一个实例, 从而节省部分 DOM 开销。下列为登入框部分代码:

const createLoginLayer = function() {
  const div = document.createElement('div')
  div.innerHTML = '登入浮框'
  div.style.display = 'none'
  document.body.appendChild(div)
  return div
}

使单例模式和创建弹框代码解耦

const getSingle = function(fn) {
  const result
  return function() {
    return result || result = fn.apply(this, arguments)
  }
}
const createSingleLoginLayer = getSingle(createLoginLayer)

document.getElementById('loginBtn').onclick = function() {
  createSingleLoginLayer()
}

代理模式

代理模式的定义:为一个对象提供一个代用品或占位符,以便控制对它的访问。

虚拟代理
下面这段代码运用代理模式来实现图片预加载,可以看到通过代理模式巧妙地将创建图片与预加载逻辑分离,并且在未来如果不需要预加载,只要改成请求本体代替请求代理对象就行。

const myImage = (function() {
  const imgNode = document.createElement('img')
  document.body.appendChild(imgNode)
  return {
    setSrc: function(src) {
      imgNode.src = src
    }
  }
})()

const proxyImage = (function() {
  const img = new Image()
  img.onload = function() { // http 图片加载完毕后才会执行
    myImage.setSrc(this.src)
  }
  return {
    setSrc: function(src) {
      myImage.setSrc('loading.jpg') // 本地 loading 图片
      img.src = src
    }
  }
})()

proxyImage.setSrc('http://loaded.jpg')

缓存代理

在原有的功能上加上结果缓存功能,就属于缓存代理。

原先有个功能是实现字符串反转(reverseString),那么在不改变 reverseString 的现有逻辑,我们可以使用缓存代理模式实现性能的优化,当然也可以在值改变的时候去处理下其他逻辑,如 Vue computed 的用法。

function reverseString(str) {
  return str
    .split('')
    .reverse()
    .join('')
}
const reverseStringProxy = (function() {
  const cached = {}
  return function(str) {
    if (cached[str]) {
      return cached[str]
    }
    cached[str] = reverseString(str)
    return cached[str]
  }
})()

订阅发布模式

在软件架构中,发布-订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在。同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者(如果有的话)存在。

从字面意思来看,我们需要首先订阅,发布者发布消息后才会收到发布的消息。不过我们还需要一个中间者来协调,从事件角度来说,这个中间者就是事件中心协调发布者和订阅者直接的消息通信

完成订阅发布整个流程需要三个角色:

  • 发布者
  • 事件中心
  • 订阅者(订阅者是可以多个的。)

以事件为例,简单流程如下:

发布者->事件中心<=>订阅者,订阅者需要向事件中心订阅指定的事件 -> 发布者向事件中心发布指定事件内容 -> 事件中心通知订阅者 -> 订阅者收到消息(可能是多个订阅者),到此完成了一次订阅发布的流程。

简单的代码实现如下:

class Event {
  constructor() {
    // 所有 eventType 监听器回调函数(数组)
    this.listeners = {}
  }
  /**
   * 订阅事件
   * @param {String} eventType 事件类型
   * @param {Function} listener 订阅后发布动作触发的回调函数,参数为发布的数据
   */
  on(eventType, listener) {
    if (!this.listeners[eventType]) {
      this.listeners[eventType] = []
    }
    this.listeners[eventType].push(listener)
  }
  /**
   * 发布事件
   * @param {String} eventType 事件类型
   * @param {Any} data 发布的内容
   */
  emit(eventType, data) {
    const callbacks = this.listeners[eventType]
    if (callbacks) {
      callbacks.forEach((c) => {
        c(data)
      })
    }
  }
}

const event = new Event()
event.on('open', (data) => {
  console.log(data)
})
event.emit('open', { open: true })

Event 可以理解为事件中心,提供了订阅和发布功能。
订阅者在订阅事件的时候,只关注事件本身,而不关心谁会发布这个事件;发布者在发布事件的时候,只关注事件本身,而不关心谁订阅了这个事件。

观察者模式

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个目标对象,当这个目标对象的状态发生变化时,会通知所有观察者对象,使它们能够自动更新。

观察者模式我们可能比较熟悉的场景就是响应式数据,如 Vue 的响应式、Mbox 的响应式。
观察者模式完成整个流程需要两个角色:

  • 目标
  • 观察者
    简单流程如下:

目标<=>观察者,观察者观察目标(监听目标)-> 目标发生变化-> 目标主动通知观察者(可能是多个)。

什么是 MVVM?与 MVC 有什么区别?

MVC、MVP 和 MVVM 是三种常见的软件架构设计模式,主要通过分离关注点的方式来组织代码结构,优化我们的开发效率。

比如说我们实验室在以前项目开发的时候,使用单页应用时,往往一个路由页面对应了一个脚本文件,所有的页面逻辑都在一个脚本文件里。页面的渲染、数据的获取,对用户事件的响应所有的应用逻辑都混合在一起,这样在开发简单项目时,可能看不出什么问题,但是一旦项目变得复杂,那么整个文件就会变得冗长,混乱,这样对我们的项目开发和后期的项目维护是非常不利的。

  • MVC 通过分离 Model、View 和 Controller 的方式来组织代码结构。其中 View 负责页面的显示逻辑,Model 负责存储页面的业务数据,以及对相应数据的操作。并且 View 和 Model 应用了观察者模式,当 Model 层发生改变的时候它会通知有关 View 层更新页面。Controller 层是 View 层和 Model 层的纽带,它主要负责用户与应用的响应操作,当用户与页面产生交互的时候,Controller 中的事件触发器就开始工作了,通过调用 Model 层,来完成对 Model 的修改,然后 Model 层再去通知 View 层更新。
  • MVVM 模式中的 VM,指的是 ViewModel,它和 MVP 的思想其实是相同的,不过它通过双向的数据绑定将 View 和 Model 的同步更新给自动化了。当 Model 发生变化的时候,ViewModel 就会自动更新;ViewModel 变化了,View 也会更新。这样就将 Presenter 中的工作给自动化了。双向数据绑定的原理,比如 vue 是通过使用数据劫持和发布订阅者模式来实现的这一功能。

今天的分享就到这里啦✨ \textcolor{red}{今天的分享就到这里啦✨} 今天的分享就到这里啦

原创不易,还希望各位大佬支持一下 \textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下

🤞 点赞,你的认可是我创作的动力! \textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向! \textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!

✏️ 评论,你的意见是我进步的财富! \textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!

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

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

相关文章

I2C知识大全系列三 —— I2C驱动之单片机中的I2C

两种方式 单片机中的I2C驱动有两种方式。一种方式是用专用硬件I2C控制器实现&#xff0c;这种方式简单易行&#xff0c;品质也容易控制&#xff0c;只是会增加硬件成本方面的压力。另一种方式是用纯软件方式实现&#xff0c;这种方式几乎无硬件成本方面的考虑。 主要对比&…

网页图片采集-网页图片采集软件免费

一款免费的网页图片采集软件可以采集网页上的各种图片&#xff0c;每个人都可以采集到各种高清图源。支持任意格式的图片采集&#xff0c;只需要导入链接即可批量采集图片。 还有更多的采集方式&#xff1a;输入关键词全网图片采集/任意网站所有图片采集&#xff01;不仅可以采…

【C++】STL——vector(万字详解)

&#x1f387;C学习历程&#xff1a;入门 博客主页&#xff1a;一起去看日落吗持续分享博主的C学习历程博主的能力有限&#xff0c;出现错误希望大家不吝赐教分享给大家一句我很喜欢的话&#xff1a; 也许你现在做的事情&#xff0c;暂时看不到成果&#xff0c;但不要忘记&…

记首次参加网络安全比赛(初赛-知识竞赛,决赛-CTF夺旗赛-解题模式)

网络安全相关的方向很多&#xff0c;几乎IT相关的安全内容都可以涵盖在内。笔者本身的知识体系更偏向于编程语言和Web应用&#xff0c;本次参赛可谓极具挑战&#xff0c;但是就是喜欢这种感觉&#xff1a;&#xff09; 赛程安排 9月16日接到通知 9月26日初赛 10月15日决赛 …

计算机网络习题答案

1、校园网属于&#xff08;局域网LAN &#xff09; 2、在下列传输介质中&#xff0c;(光缆 )传输介质的抗电磁干扰性最好。 3、光纤上采用的多路复用技术为&#xff08;WDM&#xff09; 4、计算机网络的交换方式不包括 无线交换 5、网络体系结构模型OSI模型和TCP/IP模型…

区块链实训教程(6)--开发、编译、部署、调用HelloWorld合约

文章目录1. 任务背景2. 任务目标3. 相关知识点4. 任务实操4.1 新建合约文件4.2 编写合约代码4.3 保存、编译、部署合约4.4 调用合约5. 任务总结1. 任务背景 FISCO BCOS运用智能合约进行归纳资产管理、规则定义和价值交换等操作&#xff0c;所以我们需要学习如何使用智能合约。…

aws ec2 配置jenkins和gitlab

环境搭建 下载jenkins的war包&#xff0c;启动jenkisn nohup java -jar jenkins.war --httpPort8091 > jenkins.log 2>&1 &docker安装gitlab 默认情况下&#xff0c;Omnibus GitLab 会自动为初始管理员用户账号 (root) 生成密码&#xff0c;并将其存储到 /etc…

HarmonyOS系统中内核实现温湿度采集方法

大家好&#xff0c;今天主要来聊一聊&#xff0c;如何使用鸿蒙系统中的温湿度传感器方法。 第一&#xff1a;温湿度传感器基本原理 大部分的传感器是在环境温度变化后会产生一个相应的延伸&#xff0c;因此传感器可以以不同的方式对这种反应进行信号转换。常见的大部分是电阻…

gitlab cicd 5分钟快速入门搭建私人代码仓库

gitlab 是企业级私有服务器 本文章采用docker搭建gitlab 如有不懂可微信我号yizheng369 环境准备 购买阿里云服务器&#xff0c;或者其他服务器 注意&#xff1a;本文章是用阿里云的centos 7.6作为服务器 搭建步骤 1.设置环境变量 export GITLAB_HOME/srv/gitlab2.编写dock…

今天面了个阿里拿27k出来的小哥,让我见识到了什么是天花板

2022年堪称大学生就业最难的一年&#xff0c;应届毕业生人数是1076万。失业率超50%&#xff01; 但是我观察到一个数据&#xff0c;那就是已经就业的毕业生中&#xff0c;计算机通信等行业最受毕业生欢迎&#xff01; 计算机IT行业薪资高&#xff0c;平均薪资是文科其他岗位的3…

PLC NAND 虽来但远

前言 图片来源&#xff1a; 存储随笔 2022年8月份在美国FMS峰会上&#xff0c;Solidigm公司(前身为 Intel NAND 部门) 展示了全球第一款基于PLC NAND研发的SSD。这也标志着&#xff0c;PLC时代已正式拉开序幕。出于对 PLC 的好奇&#xff0c;本文分享PLC NAND 知识&#xff0…

C/C++描述 - 矩阵乘积的计算

矩阵运算是现代科学及工程计算的基石之一&#xff0c;而矩阵乘法则是其中最常见一种运算。对于二维矩阵A、B&#xff0c;如果A的列数等于B的行数&#xff0c;则矩阵A、B可乘&#xff0c;其结果矩阵C的行数等于A的行数&#xff0c;列数等于B的列数。 本文引用自作者编写的下述图…

ArcGIS || ENVI:如何将彩色影像拆分为R、G、B以及H、S、I(B/V)影像?

目录 01 加载RGB影像数据 02 分别将三个波段进行保存 03 将RGB三色图像转化为HSI(HSB或者叫HSV)图像 04 转换的HSI图像拆分成H、S、I三个影像 首先&#xff0c;需要明确&#xff0c;手机拍摄的影像即是Red、Green、Blue三波段影像&#xff1b; 另外&#xff0c;由于方法十分…

视觉合集3

这次的合集是找到了几个论文... 一起来说下 Fast Charging of Energy-dense Lithium-ion Batteries Real-time Short Video Recommendation on Mobile Devices Semantic interpretation for convolutional neural networks: What makes a cat a cat? Prompt-to-Prompt Ima…

【论文阅读】Pre-training Methods in Information Retrieval

文章目录前言Abs1.Intro2.Background2.1.A Hierarchical View of IR2.1.1.The Core Problem View of IR2.1.2.The Framework View of IR2.1.3.The System View of IR2.2.A Brief Overview of PTMs in IR前言 因为文章篇幅较长&#xff0c;因此还在持续阅读中原文&#xff08;F…

科研初体验之Linux服务器的入门使用,关于分配了Linux账号之后怎么用,以及怎么利用Linux服务器来跑我们的python代码

前情提要 如果有人看了我之前发的乱七八糟的博客的话&#xff0c;应该就能了解到&#xff0c;我之前是计算机专业大三的学生&#xff0c;好不容易get到了保研的名额&#xff0c;前段时间就一直在操练LeetCode&#xff0c;到处报夏令营啊&#xff0c;预推免什么的&#xff0c;最…

应该了解的网络知识

今天上午10&#xff1a;00参加了一个新华三杯&#xff0c;是关于计算机网络的&#xff0c;100道题&#xff0c;发现没有一道是自己会的&#xff0c;好歹也是学过一学期的计算机网络&#xff0c;到头来发现啥也不会&#xff0c;然后现在就又去复习一下网络。 OSI七层模型 *应用层…

VUE | “面包屑”的原理

最近我在写一个“项目”&#xff1f;遇到了以前没有接触到的一个知识点——“面包屑”。 写下来&#xff0c;我所理解的思路&#xff0c;一是为了看能不能帮助到大家&#xff0c;二是自己肯定不是已经完全理解、印在脑子里了&#xff0c;所以方便自己随时复习~ 我们先来看一下…

自动化测试项目学习笔记(五):Pytest结合allure生成测试报告以及重构项目

相关文章 [ >.<] 自动化测试项目学习笔记(一)&#xff1a;unittest简单运行&#xff08;初始化&#xff0c;清除&#xff0c;设置测试行为&#xff09;[ >.<] 自动化测试项目学习笔记(二)&#xff1a;学习各种setup、tearDown、断言方法[ >.<] 自动化测试项…

启发式算法之蚁群算法

&#x1f63b;今天我们来学习启发式算法中的蚁群算法&#xff0c;据说&#xff0c;蚁群算法是路径规划算法中’最好’的群智能算法。快让我们开始吧&#xff01; 目录1. 蚁群算法基本介绍1.1 算法简介1.2 算法原理2.蚁群算法的基本流程2.1 路径构建2.2 蚂蚁信息素的更新3. scik…