Skip to content

设计模式

前端常用设计模式及其应用场景

📚 内容概览

创建型模式

结构型模式

行为型模式

前端特有模式

设计原则

🎯 学习路径

初级(理解概念)

  1. 单例模式、工厂模式
  2. 观察者模式、发布订阅
  3. 策略模式、代理模式

中级(框架应用)

  1. 装饰器模式(HOC)
  2. 中间件模式(Redux、Koa)
  3. MVVM 模式(Vue、React)

高级(架构设计)

  1. 插件化架构设计
  2. SOLID 原则应用
  3. 设计模式组合使用

🔥 面试高频

  • 说说你了解的设计模式?
  • 单例模式的应用场景?如何实现?
  • 观察者模式和发布订阅模式的区别?
  • 什么是代理模式?Vue3 响应式原理?
  • 装饰器模式在 React 中的应用?
  • 什么是中间件模式?Redux 中间件原理?
  • 如何设计一个插件化系统?
  • SOLID 原则是什么?

📊 设计模式分类

设计模式(23种)
├── 创建型(5种)
│   ├── 单例模式 ⭐⭐⭐
│   ├── 工厂模式 ⭐⭐⭐
│   ├── 抽象工厂模式
│   ├── 建造者模式 ⭐⭐
│   └── 原型模式 ⭐⭐

├── 结构型(7种)
│   ├── 代理模式 ⭐⭐⭐
│   ├── 装饰器模式 ⭐⭐⭐
│   ├── 适配器模式 ⭐⭐
│   ├── 外观模式 ⭐⭐
│   ├── 组合模式 ⭐⭐
│   ├── 桥接模式
│   └── 享元模式

└── 行为型(11种)
    ├── 观察者模式 ⭐⭐⭐
    ├── 策略模式 ⭐⭐⭐
    ├── 命令模式 ⭐⭐
    ├── 迭代器模式 ⭐⭐
    ├── 责任链模式 ⭐⭐⭐
    ├── 模板方法模式 ⭐⭐
    ├── 状态模式
    ├── 访问者模式
    ├── 中介者模式
    ├── 备忘录模式
    └── 解释器模式

⭐⭐⭐ 前端高频  ⭐⭐ 常用  ⭐ 了解即可

🚀 快速开始

单例模式

javascript
// ES6 实现
class Singleton {
  static instance = null;

  constructor() {
    if (Singleton.instance) {
      return Singleton.instance;
    }
    Singleton.instance = this;
  }
}

// 应用:Vuex Store
const store = new Vuex.Store({
  state: { count: 0 },
  mutations: {
    increment(state) {
      state.count++;
    }
  }
});

观察者模式

javascript
class EventEmitter {
  constructor() {
    this.events = {};
  }

  on(event, callback) {
    if (!this.events[event]) {
      this.events[event] = [];
    }
    this.events[event].push(callback);
  }

  emit(event, ...args) {
    if (this.events[event]) {
      this.events[event].forEach(cb => cb(...args));
    }
  }

  off(event, callback) {
    if (this.events[event]) {
      this.events[event] = this.events[event].filter(cb => cb !== callback);
    }
  }
}

// 应用:Vue 事件总线
const eventBus = new EventEmitter();
eventBus.on('update', (data) => console.log(data));
eventBus.emit('update', { msg: 'hello' });

代理模式

javascript
// 图片懒加载
class ImageProxy {
  constructor(img) {
    this.img = img;
    this.realImg = new Image();
  }

  setSrc(src) {
    this.img.src = 'loading.gif';
    this.realImg.onload = () => {
      this.img.src = src;
    };
    this.realImg.src = src;
  }
}

// 应用:Vue3 响应式
const proxy = new Proxy(target, {
  get(target, key) {
    track(target, key); // 依赖收集
    return target[key];
  },
  set(target, key, value) {
    target[key] = value;
    trigger(target, key); // 触发更新
    return true;
  }
});

装饰器模式

javascript
// React HOC
function withAuth(Component) {
  return function AuthComponent(props) {
    const isAuth = checkAuth();
    if (!isAuth) {
      return <Redirect to="/login" />;
    }
    return <Component {...props} />;
  };
}

// 使用
const ProtectedPage = withAuth(Dashboard);

策略模式

javascript
// 表单验证
const strategies = {
  required: (value, errorMsg) => {
    if (!value) return errorMsg;
  },
  minLength: (value, length, errorMsg) => {
    if (value.length < length) return errorMsg;
  },
  email: (value, errorMsg) => {
    if (!/^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(value)) {
      return errorMsg;
    }
  }
};

class Validator {
  constructor() {
    this.rules = [];
  }

  add(value, rules) {
    rules.forEach(rule => {
      const [strategy, ...args] = rule.split(':');
      this.rules.push(() => {
        return strategies[strategy](value, ...args);
      });
    });
  }

  validate() {
    for (let rule of this.rules) {
      const error = rule();
      if (error) return error;
    }
  }
}

中间件模式

javascript
// Redux 中间件
const logger = store => next => action => {
  console.log('dispatching', action);
  const result = next(action);
  console.log('next state', store.getState());
  return result;
};

// Koa 中间件
app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});

🎨 前端框架中的设计模式

React

  • 组合模式:组件树
  • 装饰器模式:HOC
  • 观察者模式:useState、useEffect
  • 策略模式:条件渲染

Vue

  • 代理模式:响应式系统(Proxy)
  • 观察者模式:依赖收集与派发更新
  • 策略模式:指令系统
  • 模板方法模式:生命周期钩子

Redux

  • 单例模式:Store
  • 观察者模式:subscribe
  • 中间件模式:applyMiddleware
  • 命令模式:Action

📖 设计原则(SOLID)

  1. 单一职责原则(SRP):一个类只负责一个功能
  2. 开闭原则(OCP):对扩展开放,对修改关闭
  3. 里氏替换原则(LSP):子类可以替换父类
  4. 接口隔离原则(ISP):使用多个专门接口,而不是单一总接口
  5. 依赖倒置原则(DIP):依赖抽象,而不是具体实现

🔗 推荐资源

  • 《JavaScript 设计模式与开发实践》- 曾探
  • 《Head First 设计模式》
  • Refactoring.Guru

前端面试知识库