设计模式应用
前端开发中常用的设计模式及实际应用场景
问题
前端开发中用过哪些设计模式?请举例说明。
解答
1. 单例模式
确保一个类只有一个实例,常用于全局状态管理。
// 单例模式 - 全局状态管理
class Store {
static instance = null;
constructor() {
if (Store.instance) {
return Store.instance;
}
this.state = {};
Store.instance = this;
}
setState(key, value) {
this.state[key] = value;
}
getState(key) {
return this.state[key];
}
}
// 使用
const store1 = new Store();
const store2 = new Store();
console.log(store1 === store2); // true
2. 发布订阅模式
解耦事件的发布者和订阅者,常用于组件通信。
// 发布订阅模式 - EventEmitter
class EventEmitter {
constructor() {
this.events = {};
}
// 订阅事件
on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
return this;
}
// 发布事件
emit(event, ...args) {
const callbacks = this.events[event];
if (callbacks) {
callbacks.forEach(cb => cb(...args));
}
return this;
}
// 取消订阅
off(event, callback) {
if (this.events[event]) {
this.events[event] = this.events[event].filter(cb => cb !== callback);
}
return this;
}
}
// 使用
const emitter = new EventEmitter();
emitter.on('login', user => console.log(`${user} 登录了`));
emitter.emit('login', '张三'); // 张三 登录了
3. 策略模式
定义一系列算法,使它们可以互相替换,常用于表单验证、价格计算。
// 策略模式 - 表单验证
const validators = {
required: value => value !== '' || '必填项',
email: value => /^[\w-]+@[\w-]+\.\w+$/.test(value) || '邮箱格式错误',
minLength: (value, len) => value.length >= len || `最少${len}个字符`,
phone: value => /^1\d{10}$/.test(value) || '手机号格式错误'
};
// 验证函数
function validate(value, rules) {
for (const rule of rules) {
const [name, ...args] = rule.split(':');
const result = validators[name](value, ...args);
if (result !== true) {
return result; // 返回错误信息
}
}
return true;
}
// 使用
console.log(validate('', ['required'])); // 必填项
console.log(validate('abc', ['email'])); // 邮箱格式错误
console.log(validate('test@qq.com', ['required', 'email'])); // true
4. 代理模式
控制对对象的访问,常用于数据劫持、缓存代理。
// 代理模式 - 响应式数据
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
console.log(`读取 ${key}`);
return target[key];
},
set(target, key, value) {
console.log(`设置 ${key} = ${value}`);
target[key] = value;
// 触发视图更新...
return true;
}
});
}
// 使用
const state = reactive({ count: 0 });
state.count; // 读取 count
state.count = 1; // 设置 count = 1
5. 装饰器模式
动态给对象添加功能,不改变原有结构。
// 装饰器模式 - 函数增强
function withLogging(fn) {
return function(...args) {
console.log(`调用 ${fn.name},参数:`, args);
const result = fn.apply(this, args);
console.log(`返回:`, result);
return result;
};
}
function add(a, b) {
return a + b;
}
// 使用
const loggedAdd = withLogging(add);
loggedAdd(1, 2);
// 调用 add,参数: [1, 2]
// 返回: 3
6. 工厂模式
封装对象创建过程,常用于组件创建。
// 工厂模式 - 创建弹窗组件
function createModal(type, options) {
const modals = {
alert: { icon: '⚠️', buttons: ['确定'] },
confirm: { icon: '❓', buttons: ['取消', '确定'] },
success: { icon: '✅', buttons: ['确定'] }
};
return {
...modals[type],
...options,
show() {
console.log(`${this.icon} ${this.message}`);
}
};
}
// 使用
const modal = createModal('confirm', { message: '确定删除吗?' });
modal.show(); // ❓ 确定删除吗?
关键点
- 单例模式:全局唯一实例,适用于 Store、缓存、配置管理
- 发布订阅:解耦组件通信,Vue/React 事件系统的基础
- 策略模式:消除 if-else,让算法可配置、可扩展
- 代理模式:Vue3 响应式原理,实现数据劫持和访问控制
- 装饰器模式:HOC、函数增强,不修改原代码添加功能
- 工厂模式:封装创建逻辑,统一管理对象实例化
目录