首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >高级前端工程师必备的 JS 设计模式入门教程,常用设计模式案例分享

高级前端工程师必备的 JS 设计模式入门教程,常用设计模式案例分享

作者头像
watermelo37
发布于 2025-05-07 06:55:57
发布于 2025-05-07 06:55:57
13300
代码可运行
举报
文章被收录于专栏:前端专精前端专精
运行总次数:0
代码可运行

高级前端工程师必备的 JS 设计模式入门教程,常用设计模式案例分享

本文适合有JavaScript基础 、 Vue/React 开发经验,但对设计模式不太熟悉的前端开发工程师。

代码语言:txt
AI代码解释
复制
    什么是设计模式?为什么要有设计模式?单例模式、工厂模式、建造者模式、适配器模式、代理模式、装饰器模式、观察者模式、策略模式、状态模式分别是什么?他们解决了什么样的问题?本文将给您答案。

一、什么是设计模式?为什么前端也要学?

1、设计模式是什么
代码语言:txt
AI代码解释
复制
    设计模式,就是**程序员们总结出来的一套解决常见代码问题的方法论**。
  • 它不是死板的规定,不是必须按部就班执行。
  • 它是经验总结,告诉你在遇到某些类型的问题时,如何写出更优雅、更健壮、更可扩展的代码。
  • 后端用,前端也用,尤其是当你的项目越来越大、多人协作越来越复杂时,设计模式就越重要。
代码语言:txt
AI代码解释
复制
    类比一下:设计模式就像打游戏时的「固定套路」,让你**在遇到不同怪物时不用每次重头想招数**,而是有一套拿得出手的打法。
2、设计模式的产出
代码语言:txt
AI代码解释
复制
    设计模式的产出不是特定代码片段,而是**一套可复用的设计思路或结构**。
  • 有些模式产出一个「结构」(比如单例产出一个唯一对象)。
  • 有些模式产出一个「流程/机制」(比如观察者产出的是发布-订阅机制)。
  • 也有些是组合型的,既有对象也有通信逻辑。
代码语言:txt
AI代码解释
复制
    设计模式产出的是「结构 + 行为」的组合,没有严格固定形式,但背后有固定的“意图”或“问题场景”。我们**关注的就是其“意图”和“场景”。**

二、设计模式在 JS 里的分类

代码语言:txt
AI代码解释
复制
    设计模式很多,但最重要的,可以分成三大类:

类型

解释

代表模式

创建型

解决「如何创建对象」的问题

单例模式、工厂模式、建造者模式

结构型

解决「对象之间怎么组织结构」的问题

适配器模式、代理模式、装饰器模式

行为型

解决「对象之间怎么协作通信」的问题

观察者模式、策略模式、状态模式

三、常用设计模式实战讲解

1、单例模式(Singleton)
代码语言:txt
AI代码解释
复制
    定义:**整个系统只存在一个实例对象**,并且能全局访问。
代码语言:txt
AI代码解释
复制
    举个例子,Vuex里面的store就是单例,事件总线(Event Bus)也是单例。
代码语言:txt
AI代码解释
复制
    来做个简单的实现,它通过一个静态属性 instance 储存实例,并在重复创建时返回已有实例,这样就能实现单例的效果:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Store {
  constructor() {
    if (Store.instance) {
      return Store.instance;
    }
    this.state = {};
    Store.instance = this;
  }
}

const a = new Store();
const b = new Store();

console.log(a === b); // true
2、工厂模式(Factory)
代码语言:txt
AI代码解释
复制
    定义:**用一个函数/类专门负责创建对象,不直接用 new。**

举几个例子,组件封装:根据类型不同返回不同组件实例还有 Axios 的实例化都是工厂模式。

代码语言:txt
AI代码解释
复制
    工厂模式的优势在于能统一创建逻辑,并且拓展非常方便,各类型之间高内聚,低耦合。做个简单的实现:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function createButton(type) {
  if (type === 'primary') {
    return { color: 'blue', size: 'large' };
  } else if (type === 'danger') {
    return { color: 'red', size: 'large' };
  }
}

const btn = createButton('primary');
console.log(btn); // { color: 'blue', size: 'large' }

工厂函数是什么?

代码语言:txt
AI代码解释
复制
    工厂函数(Factory Function)是一个**普通函数**,它**封装了创建对象的过程**,并返回这个对象。它是实现工厂模式的一种方式,但不限于工厂模式使用。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function createPerson(name, age) {
  return {
    name,
    age,
    sayHello() {
      console.log(`Hi, I'm ${name}`);
    }
  }
}

const person = createPerson('Tom', 20);
代码语言:txt
AI代码解释
复制
    这个案例中的 createPerson 就是工厂函数。
3、观察者模式(Observer)
代码语言:txt
AI代码解释
复制
    定义:**一对多关系,一个对象变化,通知所有依赖它的对象。**

比如Vue 响应式,发布订阅(EventEmitter)都属于观察者模式。

代码语言:txt
AI代码解释
复制
    一般情况下,观察者模式里面一定有一个叫做 notify / emit / publish 或类似功能的函数,用来通知所有的订阅者,这种函数本质上就是广播机制,是观察者模式的核心实现函数。做个简单的案例:维护一组回调,变化时循环触发。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Observer {
  constructor() {
    this.subscribers = [];
  }

  subscribe(fn) {
    this.subscribers.push(fn);
  }

  notify(data) {
    this.subscribers.forEach(fn => fn(data));
  }
}

const obs = new Observer();

obs.subscribe((data) => console.log('收到1', data));
obs.subscribe((data) => console.log('收到2', data));

obs.notify('你好');
// 收到1 你好
// 收到2 你好
4、代理模式(Proxy)
代码语言:txt
AI代码解释
复制
    定义:**通过一个代理对象控制对目标对象的访问。**

Vue3的响应式Proxy、接口请求封装都属于代理模式。

先用Proxy举例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const target = {
  name: '张三'
};

const proxy = new Proxy(target, {
  get(obj, prop) {
    console.log(`访问属性:${prop}`);
    return obj[prop];
  },
  set(obj, prop, value) {
    console.log(`设置属性:${prop}=${value}`);
    obj[prop] = value;
    return true;
  }
});

proxy.name; // 访问属性:name
proxy.age = 20; // 设置属性:age=20
代码语言:txt
AI代码解释
复制
    这个例子比较常见,是不是意犹未尽?我们再来一个图片懒加载的代理模式来举例:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 真正加载图片的方法
function loadImage(src) {
  const img = new Image();
  img.src = src;
  document.body.appendChild(img);
}

// 创建一个代理来控制图片加载
const proxyImage = (function () {
  let img = new Image();
  img.onload = function() {
    loadImage(this.src); // 真正加载
  }
  return function(src) {
    // 先用一张 loading 图片占位
    loadImage('loading.jpg');
    // 真正的图片异步加载完成后替换
    img.src = src;
  }
})();

// 使用
proxyImage('real-image.jpg');
代码语言:txt
AI代码解释
复制
    proxyImage 函数就是代理对象,loadImage是被代理的目标对象,用户一调用它就显示 loading 图,真正图片在加载完毕后替换。

这里使用 IIFE(立即执行函数表达式) 是为了创建**一次性的私有作用域和闭包**,隔离 img 变量,避免污染。 **执行逻辑为:**

  1. 代码刚执行时,生成了一个 proxyImage 函数,这个函数内部封装了一个私有的 Image 对象 img,并且给 img.onload 绑定了回调函数。
  2. 调用 proxyImage(src) 时,先 loadImage('loading.jpg') 显示一个占位图,再设置 img.src = src(真实图片地址)。
  3. 这时浏览器会开始异步加载 src 指向的真实图片,这一步是静默执行的,DOM渲染的是默认图片。
  4. 加载完毕后自动触发 img.onload,在回调里重新调用 loadImage(this.src),替换成真实图。
代码语言:txt
AI代码解释
复制
     其中,默认图片(loading.jpg)应该是一个极小的图,通过base64编码内嵌到代码里,或者直接用svg小图标,如果是个大一点的图片应该让浏览器预加载,以此来实现用户视角下的默认图片无感渲染。
5、策略模式(Strategy)
代码语言:txt
AI代码解释
复制
    定义:**将一系列算法封装成独立的策略类,使它们可以互相替换。**

比如一些表单验证、支付方式切换过程等。

代码语言:txt
AI代码解释
复制
    其优势在于具有开闭原则(增加新策略不用改老代码),并且代码可扩展。举例如下,其中strategies 里是具体的策略集合(算法实现),validate 是「上下文」调用器(根据情况选择策略执行),两者配合才构成完整的策略模式实现:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const strategies = {
  isNonEmpty(value) {
    return value !== '';
  },
  minLength(value, length) {
    return value.length >= length;
  }
};

function validate(value, rule, ...args) {
  return strategies[rule](value, ...args);
}

console.log(validate('abc', 'minLength', 2)); // true

开闭原则: 即对扩展开放,对修改关闭。 产生新需求时,应该通过新增代码来实现,而不是修改现有代码。这样可以减少出错的风险,提高系统的稳定性。 在策略模式中,策略模式增加新策略,只是添加新策略对象,不需要去改 validate 函数本体

代码语言:txt
AI代码解释
复制
    有没有觉得策略模式和工厂模式很像?都是通过一个“judge info”(type与rule)来判断到底该如何执行。但他们存在以下区别:

策略模式

工厂模式

关注执行逻辑不同

关注对象创建不同

替换算法/规则

替换对象

运行时切换

生成时选择

6、建造者模式、适配器模式、装饰器模式和状态模式
代码语言:txt
AI代码解释
复制
    这四个相对少见,简单介绍:
①建造者模式(Builder Pattern)
代码语言:txt
AI代码解释
复制
    **分步骤构建一个复杂对象**,而不是一口气构造。比如建一台电脑:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class ComputerBuilder {
  constructor() {
    this.computer = {};
  }
  addCPU(cpu) {
    this.computer.cpu = cpu;
    return this;
  }
  addRAM(ram) {
    this.computer.ram = ram;
    return this;
  }
  addStorage(storage) {
    this.computer.storage = storage;
    return this;
  }
  build() {
    return this.computer;
  }
}

const myComputer = new ComputerBuilder()
  .addCPU('Intel i9')
  .addRAM('32GB')
  .addStorage('1TB SSD')
  .build();
②适配器模式(Adapter Pattern)
代码语言:txt
AI代码解释
复制
    让原本接口不兼容的两个类可以一起工作。比如一个老版 API 返回的是 snake\_case,但新系统要求 camelCase:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function oldApi() {
  return { user_name: 'Tom', user_age: 20 };
}

// 适配器
function adapterApi() {
  const data = oldApi();
  return {
    userName: data.user_name,
    userAge: data.user_age
  };
}

const result = adapterApi();
③装饰器模式(Decorator Pattern)
代码语言:txt
AI代码解释
复制
    在不修改原对象的情况下,动态增加功能。比如增强 log 函数(这里相当于额外打印了时间):
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function log(msg) {
  console.log(msg);
}

// 装饰器
function withTimestamp(fn) {
  return function(...args) {
    console.log(`[${new Date().toISOString()}]`);
    return fn(...args);
  }
}

const decoratedLog = withTimestamp(log);
decoratedLog('Hello World');
④状态模式(State Pattern)
代码语言:txt
AI代码解释
复制
    对象内部状态不同,行为也不同。比如电灯开关:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Light {
  constructor() {
    this.state = 'off';
  }
  toggle() {
    if (this.state === 'off') {
      console.log('Turning on');
      this.state = 'on';
    } else {
      console.log('Turning off');
      this.state = 'off';
    }
  }
}

const light = new Light();
light.toggle(); // Turning on
light.toggle(); // Turning off

四、结语

代码语言:txt
AI代码解释
复制
    设计模式能让人写出更稳定、可维护的代码,JavaScript中最常用的设计模式有**单例、工厂、观察者、代理、策略五种。**学设计模式就相当于学解决复杂问题的套路,在框架中,如 Vue / React项目里,几乎随处可见设计模式的身影。
代码语言:txt
AI代码解释
复制
    只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
代码语言:txt
AI代码解释
复制
    其他热门文章,请关注:

极致的灵活度满足工程美学:用Vue Flow绘制一个完美流程图

你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解

DeepSeek:全栈开发者视角下的AI革命者

通过array.filter()实现数组的数据筛选、数据清洗和链式调用

通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能

TreeSize:免费的磁盘清理与管理神器,解决C盘爆满的燃眉之急

通过MongoDB Atlas 实现语义搜索与 RAG——迈向AI的搜索机制

深入理解 JavaScript 中的 Array.find() 方法:原理、性能优势与实用案例详解

el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能

MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver

JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、DOM操作等

前端实战:基于Vue3与免费满血版DeepSeek实现无限滚动+懒加载+瀑布流模块及优化策略

高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图

干货含源码!如何用Java后端操作Docker(命令行篇)

在线编程实现!如何在Java后端通过DockerClient操作Docker生成python环境

Dockerfile全面指南:从基础到进阶,掌握容器化构建的核心工具

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-05-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
学习Docker就应该掌握的dockerfile语法与指令
在日常的工作中,常常需要制作自己的项目的镜像,一般通过以下两种方式制作镜像:Docker commit、Dockerfile。
霍格沃兹测试开发
2022/06/09
6630
【云原生 | Docker篇】实战Dockerfile(五)
Dockerfile基础知识已经在上一篇做了详细介绍,如果还不是很清楚的同学可以点击传送门再复习一遍。
Lansonli
2022/05/11
8660
【云原生 | Docker篇】实战Dockerfile(五)
【重识云原生】第六章容器6.1.10节——DockerFile解析
        首先通过一张图来了解 Docker 镜像、容器和 Dockerfile 三者之间的关系。
江中散人_Jun
2022/09/30
1.6K0
【重识云原生】第六章容器6.1.10节——DockerFile解析
运维实践|Dockerfile自定义镜像
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
六月暴雪飞梨花
2023/11/28
2790
运维实践|Dockerfile自定义镜像
Dockerfile 指令
1、Dockerfile基本结构 Dockerfile由一行行命令语句组成,并且支持以#开头的注释行。
小手冰凉
2020/08/06
5280
Dockerfile 指令
Docker--DockerFile与镜像
    Dockerfile是一个用于引导docker镜像生成过程的文件,遵循其特定的语法,我们便可以创建一个自己的镜像。
洋仔聊编程
2019/01/15
1K0
万字长文带你看全网最详细Dockerfile教程
Dockerfile是用于构建Docker容器镜像的文本文件,它包含了一系列指令和配置,用于描述如何组装一个Docker容器的环境。通过Dockerfile,你可以自动化地构建镜像,确保在不同的环境中都可以复现相同的容器。Dockerfile中的指令可以指定从哪个基础镜像开始构建、复制文件到镜像中、安装软件包、设置环境变量、暴露端口、运行命令等等。每个指令都会在镜像的构建过程中创建一个新的镜像层,这些层构成了最终镜像的结构。这种分层结构让镜像的构建更加高效,同时也方便了镜像的复用和共享。以下是一个简单的Dockerfile示例:
用户1107783
2023/09/11
11.4K2
万字长文带你看全网最详细Dockerfile教程
Docker 进阶之 Dockerfile 详解
我们使用 Dockerfile 定义镜像,依赖镜像来运行容器,因此 Dockerfile 是镜像和容器的关键,Dockerfile 可以非常容易的定义镜像内容,同时在我们后期的微服务实践中,Dockerfile 也是重点关注的内容,今天我们就来一起学习它。
看、未来
2022/06/30
3.4K2
Docker 进阶之 Dockerfile 详解
一文详解Dockerfile自定义镜像
指定基础镜像,并且必须是第一条指令。如果不以任何镜像为基础,那么写法为:FROM scratch。同时意味着接下来所写的指令将作为镜像的第一层开始,语法:
一个风轻云淡
2023/11/03
1K0
DockerFile 编译语法详解
Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile来快速创建自定义的镜像,本小结首先介绍Dockerfile典型的基本结构和它支持的众多指令,并具体讲解通过这些指令来编写定制镜像的Dockerfile,以及如何生成镜像.最后介绍使用Dockerfile的一些最佳实践经验.
王 瑞
2022/12/28
4520
Docker镜像构建知识:Dockerfile 命令详解
FROM 指令用于指定其后构建新镜像所使用的基础镜像。如果本地不存在,则默认会去Docker Hub下载指定镜像。FROM指令必是Dockerfile文件中的首条命令,启动构建流程后,Docker将基于该镜像构建新镜像,FROM后的命令也会基于这个基础镜像。
废柴阿尤
2023/12/18
3.6K0
Docker 进阶指南(上)- 使用Dockerfile自定义镜像
大家好,我是洋子。上一篇文章《docker 快速入门指南》介绍了Docker的概念,安装Docker方法以及Docker的常用命令,并且在上篇内容当中,我们都是使用docker pull命令直接拉取阿里云镜像仓库里面提供的官方镜像
Bug挖掘机
2022/09/28
1.4K0
Docker 进阶指南(上)- 使用Dockerfile自定义镜像
「走进k8s」Dockerfile 基本用法(三)
PS:一般来说,应该会将 Dockerfile 置于一个空目录下,或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传给 Docker 引擎,那么可以用 .gitignore 一样的语法写一个.dockerignore,该文件是用于剔除不需要作为上下文传递给 Docker 引擎的。基本思路:1.编写.dockerignore文件 2.容器只运行单个应用 3.将多个RUN指令合并为一个 4.基础镜像的标签不要用latest 5.每个RUN指令后删除多余文件 6.选择合适的基础镜像(alpine版本最好)
IT架构圈
2019/07/30
1.8K0
「走进k8s」Dockerfile 基本用法(三)
如何用Dockerfile创建镜像
该文章介绍了如何基于CentOS 6.7,源码安装nginx。首先准备了nginx-1.9.9.tar.gz安装包和CentOS6-Base-163.repo(163源),将这两个文件放到同一目录下,并在此目录下创建名称为Dockerfile的文件。之后在此文件中实现源替换、nginx编译安装、及一些依赖包的安装。最后执行命令\"docker build -t nginx-centos:6.7 .\"以构建镜像,并将该镜像命名为nginx-centos:6.7。
古时的风筝
2018/01/08
1.7K0
Docker重学系列之Dockerfile
Dockerfile可以认为是Docker镜像的描述文件,是由一系列命令和参数构成的脚本。主要作用是用来构建docker镜像的构建文件。
大忽悠爱学习
2022/05/10
2K0
Docker重学系列之Dockerfile
docker—Dockerfile指令详解
dockerfile用来定制镜像,我们知道镜像实际上是一层一层的,镜像的定制实际上就是定制每一层所添加的配置和文件。
dogfei
2020/07/31
8130
docker容器技术系列五:Dockerfile详解
本系列教程由旺旺知识库授权进行发布 Dockerfile是一个具有规范格式的文件,根据适当的指令和语法,我们可以构建一个自定以镜像。但Dockerfile需要依赖于一个原始镜像,而这些原始镜像我们可以通过官方默认镜像仓库方便获取。具体获取方法参照前文镜像获取办法。 一、Dockerfile的基本结构 一般的,Dockerfile 分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。比如如下一个Dockerfile文件: # This dockerfile uses the ubuntu
小小科
2018/05/04
1.2K0
docker容器技术系列五:Dockerfile详解
3.Docker学习之Dockerfile
描述:Dockerfile是一个文本格式的配置文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。 用户可以使用Dockerfile快速创建自定义的镜像;通过它所支持的内部指令,以及使用它创建镜像的基本过程,Docker拥有”一点修改代替大量更新”的灵活之处;
全栈工程师修炼指南
2020/10/23
2K0
3.Docker学习之Dockerfile
Dockerfile、Docker-Compose基本命令与介绍
每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像,后续的RUN都在之前RUN提交后的镜像为基础,镜像是分层的,可以通过一个镜像的任何一个历史提交点来创建,类似源码的 版本控制 。
唐成勇
2019/05/26
2.1K0
使用 Dockerfile 创建镜像 | Docker 系列
之前写镜像的时候说到创建镜像最常用的方式是使用 Dockerfile,这篇就来重点说一下,到底是怎么使用 Dockerfile 来创建的。
AlwaysBeta
2020/11/10
8830
相关推荐
学习Docker就应该掌握的dockerfile语法与指令
更多 >
LV.0
这个人很懒,什么都没有留下~
目录
  • 一、什么是设计模式?为什么前端也要学?
    • 1、设计模式是什么
    • 2、设计模式的产出
  • 二、设计模式在 JS 里的分类
  • 三、常用设计模式实战讲解
    • 1、单例模式(Singleton)
    • 2、工厂模式(Factory)
    • 3、观察者模式(Observer)
    • 4、代理模式(Proxy)
    • 5、策略模式(Strategy)
    • 6、建造者模式、适配器模式、装饰器模式和状态模式
      • ①建造者模式(Builder Pattern)
      • ②适配器模式(Adapter Pattern)
      • ③装饰器模式(Decorator Pattern)
      • ④状态模式(State Pattern)
  • 四、结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档