前端设计模式 (Design Patterns)
设计模式是软件开发中常见问题的典型解决方案。在前端开发中,虽然很多模式被框架(如 React/Vue)隐藏了,但理解它们有助于写出更优雅的代码。
1. 单例模式 (Singleton)
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
javascript
// 场景:全局状态管理 (Vuex/Redux Store)、全局模态框
class Singleton {
constructor() {
if (!Singleton.instance) {
this.data = [];
Singleton.instance = this;
}
return Singleton.instance;
}
}
const s1 = new Singleton();
const s2 = new Singleton();
console.log(s1 === s2); // true2. 观察者模式 (Observer) / 发布-订阅模式 (Pub-Sub)
观察者模式:Subject(目标)和 Observer(观察者)直接关联。 发布-订阅模式:通过 Event Center(调度中心)作为中介,Publisher 和 Subscriber 不直接认识。
javascript
// 简单的发布-订阅 (Event Emitter)
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));
}
}
}
// 场景:Vue 的 EventBus、DOM 事件监听3. 代理模式 (Proxy)
为其他对象提供一种代理以控制对这个对象的访问。
javascript
// 场景:ES6 Proxy 实现数据响应式 (Vue 3)
const data = { count: 0 };
const proxy = new Proxy(data, {
get(target, key) {
console.log(`Reading ${key}`);
return target[key];
},
set(target, key, value) {
console.log(`Writing ${key} = ${value}`);
target[key] = value;
// 触发 UI 更新...
return true;
}
});4. 工厂模式 (Factory)
定义一个创建对象的接口,但让子类决定实例化哪一个类。
javascript
// 场景:jQuery 的 $('div'),React.createElement
function createElement(type, config) {
if (type === 'image') {
return new Image(config);
} else if (type === 'video') {
return new Video(config);
}
}5. 策略模式 (Strategy)
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。
javascript
// 场景:表单验证
const strategies = {
isNonEmpty: (val, errorMsg) => val === '' ? errorMsg : void 0,
minLength: (val, length, errorMsg) => val.length < length ? errorMsg : void 0,
isMobile: (val, errorMsg) => !/^1[3|5|8][0-9]{9}$/.test(val) ? errorMsg : void 0
};
// 使用时只需要指定使用哪个策略,而不需要写大量的 if-else6. 装饰器模式 (Decorator)
在不改变对象自身的基础上,在程序运行期间给对象动态地添加职责。
javascript
// 场景:ES7 Decorator, React HOC (高阶组件)
// @readonly
// class Person { ... }
function withLog(Component) {
return function(props) {
console.log('Rendering component...');
return <Component {...props} />;
}
}7. 适配器模式 (Adapter)
将一个类的接口转换成客户希望的另外一个接口。
javascript
// 场景:Vue 的 computed 属性(将数据适配为另一种格式),
// 或者由 Axios 适配浏览器 (XHR) 和 Node (http) 环境。