设计模式,是在实践过程中,逐渐提炼出来的一系列可复用的公共逻辑。是开发者在应对复杂问题时的重要工具。它不仅提高代码复用性和可维护性,还能使架构更加优雅
一、单例模式
单例模式的核心在于 确保一个类只有一个实例,并提供一个全局访问点。前端开发中,单例模式常用于全局状态管理,如 Vuex 或 Redux 的 Store。
优点
- 避免重复实例化,节约资源。
- 提供统一访问点,便于全局状态管理。
缺点
- 全局状态难以追踪,增加调试复杂性。
- 难以在测试环境中隔离状态。
案例
在前端,浏览器对象 window 是单例模式的天然体现,同时,单例模式也被用于配置缓存管理:
class Config {
constructor() {
if (!Config.instance) {
this.settings = {};
Config.instance = this;
}
return Config.instance;
}
set(key, value) {
this.settings[key] = value;
}
get(key) {
return this.settings[key];
}
}
const config = new Config();
config.set("theme", "dark");
二、发布-订阅模式
发布-订阅模式(又称观察者模式)通过事件总线实现模块解耦,常用于事件驱动系统。
优点
- 模块解耦:发布者与订阅者之间无需直接通信。
- 扩展性强:方便动态添加订阅者。
缺点
- 事件流复杂,调试困难。
- 管理大量事件可能造成性能开销。
案例
Vue 的事件总线($emit 和 $on)是典型实现:
class EventBus {
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 bus = new EventBus();
bus.on("data", msg => console.log(msg));
bus.emit("data", "Hello, World!");
三、原型模式
原型模式利用现有对象克隆出新对象,而非直接创建实例。在 JavaScript 中,Object.create 是其经典实现。
优点
- 避免重复初始化复杂对象。
- 提高性能,减少内存占用。
缺点
- 需要深拷贝以防止引用问题。
- 对象继承链过长时,维护困难。
案例
在配置复用或数据继承场景下常见:
const prototype = { role: "user" };
const admin = Object.create(prototype);
admin.role = "admin";
四、代理模式
代理模式通过 代理对象 对目标对象的访问进行控制。Vue3 使用 Proxy 实现响应式数据是其典型应用。
优点
- 提供额外操作(如日志、验证)。
- 支持延迟加载和缓存。
缺点
- 增加复杂性。
- 代理本身可能成为性能瓶颈。
案例
以下是一个简单的数据代理示例:
const user = { name: "Alice" };
const proxy = new Proxy(user, {
get(target, key) {
console.log(`Accessing: ${key}`);
return target[key];
},
set(target, key, value) {
console.log(`Updating: ${key} = ${value}`);
target[key] = value;
}
});
proxy.name; // 输出:Accessing: name
proxy.age = 25; // 输出:Updating: age = 25
五、组合模式
组合模式允许对象以树形结构表示整体-部分关系。前端开发中,DOM 树操作与 React 组件树是其典型应用。
优点
- 统一单一对象与组合对象的操作接口。
- 支持递归处理复杂结构。
缺点
- 对象数量庞大时性能较低。
- 类定义较多,维护复杂。
案例
class Component {
constructor(name) {
this.name = name;
this.children = [];
}
add(component) {
this.children.push(component);
}
display(indent = 0) {
console.log(`${" ".repeat(indent)}${this.name}`);
this.children.forEach(child => child.display(indent + 2));
}
}
const root = new Component("root");
const child = new Component("child");
root.add(child);
root.display();
六、迭代器模式
迭代器模式提供统一方式遍历集合,不暴露内部结构。for...of 是其 JavaScript 实现。
优点
- 支持不同数据结构统一遍历。
- 封装内部细节,简化操作。
缺点
- 实现复杂。
- 线程不安全。