设计模式应用场景
前端常用设计模式及其实际应用场景
问题
前端开发中常用哪些设计模式?各自的应用场景是什么?
解答
1. 单例模式
确保一个类只有一个实例。适用于全局状态管理、弹窗、缓存等场景。
// 单例模式 - 全局弹窗管理
class Modal {
static instance = null;
static getInstance() {
if (!Modal.instance) {
Modal.instance = new Modal();
}
return Modal.instance;
}
show(content) {
console.log('显示弹窗:', content);
}
hide() {
console.log('隐藏弹窗');
}
}
// 使用
const modal1 = Modal.getInstance();
const modal2 = Modal.getInstance();
console.log(modal1 === modal2); // true
2. 发布订阅模式
对象间一对多的依赖关系。适用于事件系统、组件通信、状态变化通知。
// 发布订阅 - 事件总线
class EventBus {
constructor() {
this.events = {};
}
// 订阅事件
on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
}
// 发布事件
emit(event, ...args) {
const callbacks = this.events[event];
if (callbacks) {
callbacks.forEach(cb => cb(...args));
}
}
// 取消订阅
off(event, callback) {
const callbacks = this.events[event];
if (callbacks) {
this.events[event] = callbacks.filter(cb => cb !== callback);
}
}
}
// 使用
const bus = new EventBus();
bus.on('login', user => console.log('用户登录:', user));
bus.emit('login', { name: '张三' }); // 用户登录: { name: '张三' }
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', ['required', 'minLength:6'])); // '最少6个字符'
console.log(validate('test@example.com', ['required', 'email'])); // true
4. 代理模式
为对象提供代理以控制访问。适用于懒加载、缓存、访问控制、Vue3 响应式。
// 代理模式 - 带缓存的请求
function createCachedFetch() {
const cache = new Map();
return new Proxy(fetch, {
apply(target, thisArg, args) {
const [url] = args;
// 命中缓存直接返回
if (cache.has(url)) {
console.log('从缓存获取:', url);
return Promise.resolve(cache.get(url));
}
// 发起请求并缓存
return target.apply(thisArg, args)
.then(res => res.json())
.then(data => {
cache.set(url, data);
return data;
});
}
});
}
const cachedFetch = createCachedFetch();
5. 装饰器模式
动态给对象添加额外职责。适用于日志记录、性能统计、权限校验、React HOC。
// 装饰器模式 - 函数增强
function withLogging(fn) {
return function (...args) {
console.log(`调用 ${fn.name},参数:`, args);
const start = Date.now();
const result = fn.apply(this, args);
console.log(`执行耗时: ${Date.now() - start}ms`);
return result;
};
}
function withErrorHandler(fn) {
return function (...args) {
try {
return fn.apply(this, args);
} catch (e) {
console.error('执行出错:', e.message);
return null;
}
};
}
// 使用
function calculate(a, b) {
return a + b;
}
const enhanced = withLogging(withErrorHandler(calculate));
enhanced(1, 2);
// 调用 calculate,参数: [1, 2]
// 执行耗时: 0ms
6. 工厂模式
封装对象创建过程。适用于根据条件创建不同类型对象。
// 工厂模式 - 创建不同类型的组件
class Button {
render() {
return '<button>按钮</button>';
}
}
class Input {
render() {
return '<input type="text" />';
}
}
class Select {
render() {
return '<select></select>';
}
}
// 工厂函数
function createComponent(type) {
const components = {
button: Button,
input: Input,
select: Select
};
const Component = components[type];
if (!Component) {
throw new Error(`未知组件类型: ${type}`);
}
return new Component();
}
// 使用
const btn = createComponent('button');
console.log(btn.render()); // <button>按钮</button>
关键点
- 单例模式:全局唯一实例,用于弹窗、Store、缓存
- 发布订阅:解耦组件通信,Vue/React 事件系统的基础
- 策略模式:消除 if-else,表单验证、价格计算常用
- 代理模式:控制访问,Vue3 响应式、懒加载、缓存代理
- 装饰器模式:不修改原函数增强功能,HOC、日志、权限
- 工厂模式:封装创建逻辑,根据类型动态创建对象
目录