前端使用7种设计模式的核心原则

7种设计模式

设计模式按功能分3类,本文覆盖全部核心类型,掌握这7种就能应对80%的前端场景:

  • 结构型:亨元模式、单例模式(优化代码结构,提升复用)

  • 行为型:备忘录、中介者、迭代器、发布-订阅(规范对象交互,降低耦合)

  • 创建型:工厂模式(规范对象创建,简化逻辑)

一、结构型模式:让代码结构更灵活

核心解决"类/对象怎么组合"的问题,重点是复用和灵活扩展。

1. 亨元模式:能共享的就不重复造

核心思想:大量相似对象只创建一次公共部分,独有的部分单独传参,节省内存。

前端场景:页面渲染多个相同样式的图标(比如列表里的"编辑"图标)

案例

javascript 复制代码
// 1. 共享的图标对象(公共部分:图标类型、地址)
class Icon {
  constructor(type) {
    this.type = type; // 比如"编辑""删除"
    this.url = `/icons/${type}.png`; // 共享的图标地址
  }
  // 渲染时传独有的位置(外部状态)
  render(x, y) {
    console.log(`渲染${this.type}图标,位置(${x},${y})`);
  }
}

// 2. 管理共享对象的工厂:确保同类型只创建一次
class IconFactory {
  constructor() {
    this.iconMap = {}; // 缓存已创建的图标
  }
  getIcon(type) {
    // 有就复用,没有就新建
    if (!this.iconMap[type]) {
      this.iconMap[type] = new Icon(type);
    }
    return this.iconMap[type];
  }
}

// 使用:渲染10个编辑图标,实际只创建1个对象
const factory = new IconFactory();
for (let i = 0; i < 10; i++) {
  // 复用同一个"编辑"图标,只改位置
  factory.getIcon('edit').render(i * 50, 10);
}
console.log(Object.keys(factory.iconMap).length); // 1(只创建了1个对象)

2. 单例模式:全局只有一个实例

核心思想:一个类在整个应用里只有一个对象,避免重复创建浪费资源。

前端场景:全局的Toast提示、弹窗管理器(整个页面只能有一个Toast)

案例

javascript 复制代码
// 全局唯一的Toast管理器
class Toast {
  constructor() {
    this.showing = false; // 标记是否正在显示
  }
  // 显示Toast
  show(text) {
    if (this.showing) return; // 避免重复显示
    this.showing = true;
    console.log(`显示Toast:${text}`);
    // 3秒后隐藏
    setTimeout(() => {
      this.showing = false;
    }, 3000);
  }
  // 静态方法:获取全局唯一实例
  static getInstance() {
    if (!Toast.instance) {
      Toast.instance = new Toast();
    }
    return Toast.instance;
  }
}

// 使用:多次调用,都是同一个实例
const toast1 = Toast.getInstance();
const toast2 = Toast.getInstance();
toast1.show('操作成功'); // 显示Toast:操作成功
toast2.show('重复调用'); // 不生效(正在显示中)
console.log(toast1 === toast2); // true(同一个实例)

二、行为型模式:让对象交互更高效

核心解决"对象之间怎么通信、怎么控制行为"的问题,重点是解耦。

1. 备忘录模式:保存状态,支持撤销

核心思想:偷偷保存对象的状态,后续想恢复时直接用,不破坏原代码。

前端场景:输入框的撤销功能、表单重置

案例

javascript 复制代码
// 1. 备忘录:专门保存状态(只存不改)
class Memento {
  constructor(state) {
    this.state = state; // 保存输入框的内容
  }
  getState() {
    return this.state; // 提供获取状态的方法
  }
}

// 2. 输入框(需要保存状态的对象)
class InputBox {
  constructor() {
    this.value = ''; // 输入框当前值
  }
  // 更新输入值
  setValue(val) {
    this.value = val;
  }
  // 保存当前状态到备忘录
  saveState() {
    return new Memento(this.value);
  }
  // 从备忘录恢复状态(撤销)
  restoreState(memento) {
    this.value = memento.getState();
  }
}

// 使用:输入框撤销功能
const input = new InputBox();
const history = []; // 保存历史状态

// 第一步:输入"hello",保存状态
input.setValue('hello');
history.push(input.saveState());
console.log('当前输入:', input.value); // hello

// 第二步:输入"world",保存状态
input.setValue('hello world');
history.push(input.saveState());
console.log('当前输入:', input.value); // hello world

// 第三步:撤销到上一步
input.restoreState(history[0]);
console.log('撤销后:', input.value); // hello

2. 中介者模式:所有交互都走"中间人"

核心思想:多个对象不直接通信,都通过一个"中介者"传话,降低耦合。

前端场景:兄弟组件通信、聊天室消息转发

案例

javascript 复制代码
// 1. 中介者(中间人:转发消息)
class Mediator {
  constructor() {
    this.users = []; // 所有需要通信的对象
  }
  // 注册对象
  addUser(user) {
    this.users.push(user);
    user.mediator = this; // 给对象绑定中介者
  }
  // 转发消息:A发的消息,转给其他人
  sendMsg(msg, sender) {
    this.users.forEach(user => {
      if (user !== sender) { // 不发给自己
        user.receiveMsg(msg);
      }
    });
  }
}

// 2. 通信对象(比如聊天室用户)
class User {
  constructor(name) {
    this.name = name;
  }
  // 发消息(通过中介者)
  sendMsg(msg) {
    console.log(`${this.name}发送:${msg}`);
    this.mediator.sendMsg(msg, this);
  }
  // 收消息
  receiveMsg(msg) {
    console.log(`${this.name}收到:${msg}`);
  }
}

// 使用:3人聊天室
const mediator = new Mediator();
const user1 = new User('张三');
const user2 = new User('李四');

mediator.addUser(user1);
mediator.addUser(user2);

user1.sendMsg('你好'); 
// 输出:张三发送:你好 → 李四收到:你好

3. 迭代器模式:用统一方式遍历不同数据

核心思想:不管是数组、对象,都用同样的方法遍历,不用关心底层结构。

前端场景:遍历不同数据源(比如同时遍历数组和对象)

案例

javascript 复制代码
// 迭代器:统一遍历逻辑
class Iterator {
  constructor(data) {
    this.data = data;
    this.index = 0;
    // 把对象转为数组,方便统一处理
    if (typeof data === 'object' && !Array.isArray(data)) {
      this.data = Object.entries(data);
    }
  }
  // 遍历所有元素,执行回调
  each(callback) {
    while (this.index < this.data.length) {
      callback(this.data[this.index]);
      this.index++;
    }
  }
}

// 使用:用同样的each方法遍历数组和对象
// 1. 遍历数组
new Iterator([1, 2, 3]).each(item => {
  console.log('数组元素:', item); // 1 2 3
});

// 2. 遍历对象
new Iterator({ name: '张三', age: 20 }).each(([key, val]) => {
  console.log('对象属性:', `${key}=${val}`); // name=张三 age=20
});

4. 发布-订阅模式:事件驱动,灵活通信

核心思想:有人"发布"事件,有人"订阅"事件,发布后所有订阅者都会收到通知。

前端场景:跨层级组件通信、全局事件监听(比如页面滚动回调)

案例

javascript 复制代码
// 事件总线(发布-订阅中心)
class EventBus {
  constructor() {
    this.events = {}; // 存储事件:{ 事件名: [回调1, 回调2] }
  }
  // 订阅事件(监听)
  on(eventName, callback) {
    if (!this.events[eventName]) {
      this.events[eventName] = [];
    }
    this.events[eventName].push(callback);
  }
  // 发布事件(触发)
  emit(eventName, ...args) {
    // 触发该事件的所有回调
    this.events[eventName]?.forEach(callback => {
      callback(...args);
    });
  }
}

// 使用:全局事件通信
const eventBus = new EventBus();

// 订阅"login"事件(监听登录成功)
eventBus.on('login', (username) => {
  console.log(`欢迎${username}登录`);
});

// 发布"login"事件(触发登录成功)
eventBus.emit('login', '张三'); // 输出:欢迎张三登录

三、创建型模式:让对象创建更简单

核心解决"怎么创建对象"的问题,重点是简化创建逻辑,避免重复代码。

工厂模式:找工厂要对象,不用自己new

核心思想:把对象的创建逻辑封装在工厂里,想要对象时直接找工厂要,不用关心创建细节。

前端场景:创建不同类型的弹窗(成功、错误、警告弹窗)

案例

javascript 复制代码
// 1. 不同类型的弹窗(产品)
class SuccessAlert {
  show(msg) {
    console.log(`正缺${msg}`);
  }
}

class ErrorAlert {
  show(msg) {
    console.log(`错误 ${msg}`);
  }
}

// 2. 弹窗工厂(封装创建逻辑)
class AlertFactory {
  // 根据类型创建不同弹窗
  createAlert(type) {
    switch (type) {
      case 'success':
        return new SuccessAlert();
      case 'error':
        return new ErrorAlert();
    }
  }
}

// 使用:通过工厂创建弹窗,不用自己new
const factory = new AlertFactory();
const successAlert = factory.createAlert('success');
successAlert.show('操作成功'); //  操作成功

const errorAlert = factory.createAlert('error');
errorAlert.show('操作失败'); //  操作失败

四、7种模式速查表(快速记忆)

模式名称 核心思想 前端简单场景
亨元模式 共享相似对象,减少创建 渲染大量相同图标
单例模式 全局唯一实例 全局Toast管理器
备忘录模式 保存状态,支持撤销 输入框撤销
中介者模式 通过中间人通信,解耦 兄弟组件通信
迭代器模式 统一遍历不同数据 遍历数组/对象
发布-订阅模式 事件驱动,发布订阅 跨层级组件通信
工厂模式 工厂封装创建逻辑 创建不同类型弹窗
相关推荐
蜕变菜鸟2 小时前
折叠页面 css
前端
菩提小狗2 小时前
小迪安全2022-2023|第35天:WEB攻防-通用漏洞&XSS跨站&反射&存储&DOM&盲打&劫持|web安全|渗透测试|
前端·安全·xss
子春一2 小时前
Flutter for OpenHarmony:构建一个专业级 Flutter 节拍器,深入解析定时器、状态同步与音乐节奏交互设计
javascript·flutter·交互
这个昵称也不能用吗?2 小时前
React 19 【use】hook使用简介
前端·react.js·前端框架
web小白成长日记2 小时前
修复 Storybook MDX 中 “does not provide an export named ‘ArgsTable‘” 的实战
前端
Aotman_2 小时前
Vue <template v-for> key should be placed on the <template> tag.
前端·javascript·vue.js
智绘前端2 小时前
GitHub 登录功能开发 SOP
人工智能·typescript·github·reactjs
摘星编程3 小时前
在OpenHarmony上用React Native:自定义useTranslation翻译功能
javascript·react native·react.js
A_nanda3 小时前
vue快速学习框架
前端·javascript·vue.js·学习·c#