一、设计模式的本质与分类
定义:设计模式是软件开发中反复出现的问题的通用解决方案,由GoF(四人组)在1994年归纳为23种经典模式。
三大分类:
- 创建型模式:解决对象创建问题(如单例、工厂);
- 结构型模式:解决对象组合问题(如装饰器、适配器);
- 行为型模式:解决对象交互问题(如观察者、策略)。
二、创建型模式(解决对象创建)
1. 单例模式(Singleton)
- 核心思想:确保类只有一个实例,全局可访问。
- 实现要点:
class Singleton { constructor() { if (!Singleton.instance) { Singleton.instance = this; } return Singleton.instance; } } // 使用 const s1 = new Singleton(); const s2 = new Singleton(); console.log(s1 === s2); // true
- 应用场景:全局状态管理(如Vuex的store)、弹窗管理器。
2. 工厂模式(Factory)
- 核心思想:将对象创建逻辑封装,客户端无需知道具体实现。
- 简单工厂示例:
// 产品接口 class Product { constructor(name) { this.name = name; } use() { console.log(`使用${this.name}`); } } // 工厂 class Factory { createProduct(name) { return new Product(name); } } // 使用 const factory = new Factory(); const product = factory.createProduct('手机'); product.use(); // 使用手机
- 应用场景:Vue组件动态注册、前端路由配置。
三、结构型模式(解决对象组合)
1. 装饰器模式(Decorator)
- 核心思想:动态为对象添加新功能,不修改原类。
- 示例(为函数添加日志功能):
// 原始函数 function doTask() { console.log('执行任务'); } // 装饰器 function withLog(func) { return function() { console.log('开始时间:', new Date()); const result = func.apply(this, arguments); console.log('结束时间:', new Date()); return result; }; } // 使用 const taskWithLog = withLog(doTask); taskWithLog(); // 输出:开始时间... 执行任务 结束时间...
- 应用场景:React高阶组件(HOC)、Redux的middleware。
2. 适配器模式(Adapter)
- 核心思想:将不兼容的接口转换为兼容的接口。
- 示例(适配旧API):
// 旧接口 const oldAPI = { fetchData: function(callback) { // 回调风格API setTimeout(() => callback('旧数据'), 100); } }; // 适配器 const adapter = { fetchData() { return new Promise((resolve) => { oldAPI.fetchData(resolve); }); } }; // 使用Promise风格 adapter.fetchData().then(data => console.log(data));
- 应用场景:兼容不同浏览器API(如EventEmitter适配器)。
四、行为型模式(解决对象交互)
1. 观察者模式(Observer)
- 核心思想:对象间建立一对多依赖,当一个对象变化时,所有依赖者都会收到通知。
- 示例(事件总线):
class EventEmitter { constructor() { this.events = {}; } on(event, callback) { if (!this.events[event]) this.events[event] = []; this.events[event].push(callback); } emit(event, data) { if (this.events[event]) { this.events[event].forEach(callback => callback(data)); } } } // 使用 const emitter = new EventEmitter(); emitter.on('message', (data) => console.log('收到消息:', data)); emitter.emit('message', 'Hello'); // 收到消息: Hello
- 应用场景:Vue的响应式系统、DOM事件机制。
2. 策略模式(Strategy)
- 核心思想:定义一系列算法,将每个算法封装,使它们可互换。
- 示例(表单验证):
const strategies = { isRequired(value) { return value ? true : '不能为空'; }, isEmail(value) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) ? true : '请输入正确邮箱'; } }; class Validator { constructor() { this.rules = []; } add(field, strategy, errorMsg) { this.rules.push(() => { const value = this[field]; const result = strategies[strategy](value); return result === true ? '' : `${field} ${result}`; }); } validate() { for (const rule of this.rules) { const error = rule(); if (error) return error; } return ''; } } // 使用 const form = new Validator(); form.add('username', 'isRequired', '必填'); form.add('email', 'isEmail', '格式错误'); form.username = ''; form.email = 'invalid'; console.log(form.validate()); // username 必填
- 应用场景:排序算法切换、动画效果策略。
五、问题
1. 问:前端中常用的设计模式有哪些?请举例说明。
答:
- 单例模式:Vuex的store、全局状态管理;
- 观察者模式:Vue的响应式系统、事件总线(EventBus);
- 装饰器模式:React高阶组件(HOC)、Redux middleware;
- 工厂模式:Vue组件动态创建、Element UI的组件工厂;
- 适配器模式:不同浏览器API兼容(如Fetch API适配器)。
2. 问:装饰器模式和继承的区别是什么?
答:
- 装饰器模式:
- 动态添加功能,不修改原类;
- 一个对象可被多个装饰器装饰(如React组件被多个HOC包裹);
- 符合开闭原则(对扩展开放,对修改关闭)。
- 继承:
- 静态继承父类功能,需修改类结构;
- 单继承限制(JS中类只能继承一个父类);
- 可能导致类层次复杂(“继承地狱”)。
3. 问:为什么React Hooks替代了部分设计模式?
答:
- 状态逻辑复用:Hooks(如
useEffect
、useReducer
)替代了装饰器模式(HOC)的部分场景,避免组件嵌套过深; - 简化组件结构:Hooks使逻辑抽离更灵活(如
useFetch
自定义Hook替代适配器模式); - 性能优化:Hooks减少了组件重渲染范围,比高阶组件更高效。
六、设计原则与模式的关系
四大设计原则(SOLID):
- 单一职责(Single Responsibility):一个类只负责一项职责;
- 开闭原则(Open-Closed):软件实体对扩展开放,对修改关闭;
- 里氏替换(Liskov Substitution):子类可替换父类且不破坏程序;
- 接口隔离(Interface Segregation):多个特定接口优于单一大接口;
- 依赖倒置(Dependency Inversion):高层模块不依赖低层模块,依赖抽象。
关系:设计模式是实现设计原则的具体方案,如:
- 单例模式体现单一职责;
- 装饰器模式遵循开闭原则;
- 工厂模式实现依赖倒置。