Javascript中的一些常见设计模式

发布于:2025-08-09 ⋅ 阅读:(13) ⋅ 点赞:(0)

1. 单例模式(Singleton Pattern)

核心思想

  • 一个类只能有一个实例,并提供一个全局访问点。

场景

  • 全局缓存
  • Vuex / Redux 中的 store
  • 浏览器中的 localStorage 管理类

示例

const Singleton = (function () {
  let instance;

  function createInstance() {
    return { name: "我是唯一的实例" };
  }

  return {
    getInstance: function () {
      if (!instance) {
        instance = createInstance();
      }
      return instance;
    }
  };
})();

const a = Singleton.getInstance();
const b = Singleton.getInstance();
console.log(a === b); // true

2. 工厂模式(Factory Pattern)

核心思想

  • 不直接使用 new 去创建对象,而是通过一个工厂函数根据条件返回不同的实例。

场景

  • 创建大量结构相似的对象
  • 根据不同参数创建不同对象

示例

function AnimalFactory(type) {
  switch (type) {
    case 'dog':
      return { sound: () => console.log("汪汪") };
    case 'cat':
      return { sound: () => console.log("喵喵") };
    default:
      return { sound: () => console.log("未知动物") };
  }
}

const dog = AnimalFactory('dog');
dog.sound(); // 汪汪

//封装new
function AnimalFactory(type) {
  if (type === 'dog') return new Dog();
  if (type === 'cat') return new Cat();
  throw new Error("Unknown type");
}

const pet1 = AnimalFactory('dog'); // 外部不再直接 new
const pet2 = AnimalFactory('cat');

3. 策略模式(Strategy Pattern)

核心思想

  • 定义一系列算法,把它们封装起来,并且可以互相替换。

场景

  • 表单验证
  • 多种支付方式选择
  • AI 策略切换

示例

const strategies = {
  isNotEmpty: val => val !== '',
  isMobile: val => /^1[3-9]\d{9}$/.test(val),
  minLength: (val, len) => val.length >= len
};

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

console.log(validate('isMobile', '13888888888')); // true

4. 观察者模式(Observer Pattern)

核心思想

  • 对象维护一个观察者列表,当自身状态发生变化时,主动通知这些观察者。
  • 解耦发布者与订阅者之间的关系,实现一对多的通知机制。

角色

  • Subject(目标对象):被观察的对象,维护一个观察者列表
  • Observer(观察者):订阅目标对象的变化,目标对象变化后会通知观察者

场景

  • Vue 的响应式数据
  • 发布订阅
  • DOM 事件系统

示例

class Subject {
  constructor() {
    this.observers = [];
  }

  addObserver(observer) {
    this.observers.push(observer);
  }

  notify(data) {
    this.observers.forEach(observer => observer.update(data));
  }
}

class Observer {
  constructor(name) {
    this.name = name;
  }

  update(data) {
    console.log(`${this.name} 收到通知:`, data);
  }
}

const subject = new Subject();
subject.addObserver(new Observer("A"));
subject.addObserver(new Observer("B"));

subject.notify("状态变更啦!"); 
//A 收到通知: 状态变更啦!
//B 收到通知: 状态变更啦!

5.中介者模式(Mediator Pattern)

核心思想

  • 避免多个对象之间形成网状结构,实现对象之间的解耦协作。

角色

  • Mediator(中介者):封装对象之间的通信,处理对象之间的交互逻辑
  • Colleague(同事类):不再相互通信,而是和中介者打交道

示例

class Mediator {
  constructor() {
    this.users = {};
  }

  register(user) {
    this.users[user.name] = user;
    user.mediator = this;
  }

  send(message, from, to) {
    if (this.users[to]) {
      this.users[to].receive(message, from);
    }
  }
}

class User {
  constructor(name) {
    this.name = name;
    this.mediator = null;
  }

  send(message, to) {
    this.mediator.send(message, this.name, to);
  }

  receive(message, from) {
    console.log(`${this.name} 收到来自 ${from} 的消息: ${message}`);
  }
}

const mediator = new Mediator();
const alice = new User("Alice");
const bob = new User("Bob");

mediator.register(alice);
mediator.register(bob);

alice.send("Hi Bob", "Bob");

6. 装饰器模式(Decorator Pattern)

核心思想

  • 不修改原有对象结构的前提下,动态扩展其功能。

场景

  • Vue 的组件装饰器(@Component)
  • 对函数、方法添加日志、缓存、权限控制等

示例

function logDecorator(fn) {
  return function (...args) {
    console.log("调用前:", args);
    const result = fn.apply(this, args);
    console.log("调用后:", result);
    return result;
  }
}

function sum(a, b) {
  return a + b;
}

const decoratedSum = logDecorator(sum);
decoratedSum(1, 2);
// 调用前:[1, 2]
// 调用后:3

7. 代理模式(Proxy Pattern)

核心思想

  • 通过一个代理对象控制对另一个对象的访问。

场景

  • 数据拦截与监控(如 Vue3 响应式 Proxy)
  • 图片懒加载
  • 网络请求代理

示例

const target = {
  name: "qiqi",
  age: 28
};

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 = 30;   // 设置 age 为 30

8. 外观模式(Facade Pattern)

核心思想

  • 提供一个统一的接口,屏蔽复杂系统的内部细节。

场景

  • 封装复杂 API
  • 统一调用入口
  • 浏览器兼容性封装

示例

function ajaxFacade(url, method, data) {
  return fetch(url, {
    method,
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data)
  }).then(res => res.json());
}

// 使用
ajaxFacade('/api/login', 'POST', { name: 'qiqi' });

9. 发布订阅模式(Publish-Subscribe Pattern)

核心思想

  • 通过事件中心管理多个对象之间的通信,发布者与订阅者之间不直接关联。

与观察者模式类似,但通过中间调度器来解耦。

场景

  • 事件总线 EventBus
  • 跨组件通信
  • 消息队列

示例:JS 中的自定义实现

const EventBus = {
  events: {},
  on(event, handler) {
    if (!this.events[event]) this.events[event] = [];
    this.events[event].push(handler);
  },
  emit(event, data) {
    (this.events[event] || []).forEach(fn => fn(data));
  }
};

EventBus.on('login', data => console.log("登录成功:", data));
EventBus.emit('login', { user: 'qiqi' }); //登录成功: { user: 'qiqi' }

在 Vue 中用法

创建 EventBus 实例:

// event-bus.js
import Vue from 'vue';
export const EventBus = new Vue();

在组件 A 中监听事件(订阅):

// ComponentA.vue
import { EventBus } from './event-bus';

export default {
  created() {
    EventBus.$on('sayHello', (msg) => {
      console.log('收到消息:', msg);
    });
  },
  beforeDestroy() {
    EventBus.$off('sayHello'); // 清除监听
  }
}

在组件 B 中发送事件(发布):

// ComponentB.vue
import { EventBus } from './event-bus';

export default {
  methods: {
    sendMsg() {
      EventBus.$emit('sayHello', '你好,我是B组件');
    }
  }
}

Vue 源码中的 EventsMixin (精简):

function EventsMixin(Vue) {
  Vue.prototype.$on = function (event, fn) {
    const vm = this;
    if (!vm._events) vm._events = {};
    if (!vm._events[event]) vm._events[event] = [];
    vm._events[event].push(fn);
  }

  Vue.prototype.$emit = function (event, ...args) {
    const vm = this;
    const cbs = vm._events && vm._events[event];
    if (cbs) {
      cbs.forEach(cb => cb(...args));
    }
  }

  Vue.prototype.$off = function (event, fn) {
    const vm = this;
    if (!vm._events) return;

    // 省略部分逻辑,只保留关键流程
    if (!fn) {
      delete vm._events[event];
    } else {
      vm._events[event] = vm._events[event].filter(cb => cb !== fn);
    }
  }
}

Vue2 中常用的设计模式

  1. 观察者模式(Observer Pattern)
    • 用途:实现响应式系统。
    • 核心机制:Dep 和 Watcher。
      • 数据变化 → 通知订阅者(watcher) → 更新视图。

关键代码:

Object.defineProperty(obj, 'key', {
  get() {
    // 依赖收集
  },
  set(newVal) {
    // 通知 watcher 更新
  }
});
  1. 发布-订阅模式(Publish-Subscribe)

    • 用途:事件总线(EventBus)。
      • 用于组件间通信,特别是没有父子关系的组件。
    • 实现方式:通过 $on、$emit、$off 方法注册、触发和注销事件。
  2. 工厂模式(Factory Pattern)

    • 用途:创建组件实例、VNode 等。
    • 示例:Vue.extend() 实际上就是创建一个“组件构造器”。

Vue3 中常用的设计模式

  1. 观察者模式(Observer Pattern)
    • 用途:响应式系统升级为 Proxy。
    • 与 Vue2 区别:用 Proxy 替代了 Object.defineProperty,更强大、无死角。
    • 核心机制:effect()、reactive()、track()、trigger()。
  2. 组合模式(Composite Pattern)
    • 用途:组合式 API(Composition API)。
      • 将逻辑组合成小函数(setup() 中的 hooks),类似树状结构组织功能逻辑。
      • 更灵活地组合复用功能。
  3. 代理模式(Proxy Pattern)
    • 用途:响应式对象封装。
const state = reactive({ count: 0 });

reactive 返回的对象是 Proxy 的代理,拦截读写操作。

  1. 依赖注入模式(DI Pattern)
    • 用途:通过 provide / inject 实现跨层级组件通信。
  2. 策略模式(Strategy Pattern)
    • 用途:compiler 和 patch 阶段,Vue 会根据不同平台(Web、SSR、Native)选择不同策略处理渲染。

网站公告

今日签到

点亮在社区的每一天
去签到