引言
设计模式是软件工程中经过验证的解决方案模板,能帮助开发者写出更优雅、可维护的代码。在前端开发中,合理运用设计模式可以显著提升代码质量。今天我们来深入探讨三种最常用的设计模式:单例模式 、工厂模式 和观察者模式。
一、单例模式(Singleton Pattern)
核心概念
单例模式确保一个类只有一个实例,并提供全局访问点。这在需要共享资源的场景中非常有用,比如数据库连接、配置管理、状态存储等。
实现方式
1. 基础实现
javascript
class Singleton {
constructor() {
if (Singleton.instance) {
return Singleton.instance;
}
Singleton.instance = this;
}
getData() {
return this.data;
}
setData(value) {
this.data = value;
}
}
// 使用
const instance1 = new Singleton();
const instance2 = new Singleton();
console.log(instance1 === instance2); // true
2. 惰性初始化(推荐)
javascript
class LazySingleton {
static instance = null;
static getInstance() {
if (!LazySingleton.instance) {
LazySingleton.instance = new LazySingleton();
}
return LazySingleton.instance;
}
constructor() {
// 私有化构造函数
if (LazySingleton.instance) {
throw new Error('Use getInstance() instead');
}
}
}
// 使用
const singleton1 = LazySingleton.getInstance();
const singleton2 = LazySingleton.getInstance();
console.log(singleton1 === singleton2); // true
3. 实际应用:全局状态管理
javascript
class Store {
static instance = null;
static getInstance() {
if (!Store.instance) {
Store.instance = new Store();
}
return Store.instance;
}
constructor() {
this.state = {};
this.listeners = [];
}
setState(key, value) {
this.state[key] = value;
this.notify();
}
getState(key) {
return this.state[key];
}
subscribe(callback) {
this.listeners.push(callback);
}
notify() {
this.listeners.forEach(cb => cb(this.state));
}
}
// 使用
const store1 = Store.getInstance();
const store2 = Store.getInstance();
store1.setState('user', { name: '张三' });
console.log(store2.getState('user')); // { name: '张三' }
二、工厂模式(Factory Pattern)
核心概念
工厂模式用于创建对象,而无需指定具体的类。它提供了一种将对象创建逻辑封装起来的方式,提高代码的灵活性和可扩展性。
实现方式
1. 简单工厂
typescript
class User {
constructor(name, email) {
this.name = name;
this.email = email;
}
greet() {
return `Hello, I'm ${this.name}`;
}
}
class Admin {
constructor(name, email, role) {
this.name = name;
this.email = email;
this.role = role;
}
greet() {
return `Hello, I'm ${this.name}, admin`;
}
canManage() {
return true;
}
}
// 工厂函数
function createUser(type, name, email, role) {
if (type === 'user') {
return new User(name, email);
} else if (type === 'admin') {
return new Admin(name, email, role);
}
throw new Error('Invalid user type');
}
// 使用
const user = createUser('user', '张三', 'zhang@example.com');
const admin = createUser('admin', '李四', 'li@example.com', 'super');
console.log(user.greet()); // Hello, I'm 张三
console.log(admin.canManage()); // true
2. 工厂类
typescript
class ComponentFactory {
static create(type, config) {
switch (type) {
case 'button':
return new ButtonComponent(config);
case 'input':
return new InputComponent(config);
case 'modal':
return new ModalComponent(config);
default:
throw new Error(`Unknown component type: ${type}`);
}
}
}
class ButtonComponent {
constructor({ label, onClick }) {
this.label = label;
this.onClick = onClick;
}
render() {
return `<button onclick="${this.onClick}">${this.label}</button>`;
}
}
class InputComponent {
constructor({ placeholder, type = 'text' }) {
this.placeholder = placeholder;
this.type = type;
}
render() {
return `<input type="${this.type}" placeholder="${this.placeholder}">`;
}
}
class ModalComponent {
constructor({ title, content }) {
this.title = title;
this.content = content;
}
render() {
return `
<div class="modal">
<h2>${this.title}</h2>
<p>${this.content}</p>
</div>
`;
}
}
// 使用
const button = ComponentFactory.create('button', {
label: '点击',
onClick: 'alert("clicked")'
});
const input = ComponentFactory.create('input', {
placeholder: '请输入...'
});
console.log(button.render());
console.log(input.render());
3. 实际应用:API 请求工厂
typescript
class APIFactory {
static create(type) {
const baseURL = 'https://api.example.com';
switch (type) {
case 'users':
return new UsersAPI(baseURL);
case 'posts':
return new PostsAPI(baseURL);
case 'comments':
return new CommentsAPI(baseURL);
default:
throw new Error('Unknown API type');
}
}
}
class BaseAPI {
constructor(baseURL) {
this.baseURL = baseURL;
}
async request(endpoint, options = {}) {
const response = await fetch(`${this.baseURL}${endpoint}`, {
...options,
headers: {
'Content-Type': 'application/json',
...options.headers
}
});
return response.json();
}
}
class UsersAPI extends BaseAPI {
async getAll() {
return this.request('/users');
}
async getById(id) {
return this.request(`/users/${id}`);
}
async create(data) {
return this.request('/users', {
method: 'POST',
body: JSON.stringify(data)
});
}
}
class PostsAPI extends BaseAPI {
async getAll() {
return this.request('/posts');
}
async getByUser(userId) {
return this.request(`/posts?userId=${userId}`);
}
}
// 使用
const usersAPI = APIFactory.create('users');
const postsAPI = APIFactory.create('posts');
// 获取所有用户
usersAPI.getAll().then(users => console.log(users));
// 获取某用户的所有文章
postsAPI.getByUser(1).then(posts => console.log(posts));
三、观察者模式(Observer Pattern)
核心概念
观察者模式定义了一种一对多的依赖关系,当一个对象(被观察者)状态改变时,所有依赖它的对象(观察者)都会收到通知。这是前端事件系统和状态管理的核心模式。
实现方式
1. 基础实现
javascript
class Subject {
constructor() {
this.observers = [];
}
attach(observer) {
this.observers.push(observer);
}
detach(observer) {
this.observers = this.observers.filter(obs => obs !== observer);
}
notify(data) {
this.observers.forEach(observer => observer.update(data));
}
}
class Observer {
constructor(name) {
this.name = name;
}
update(data) {
console.log(`${this.name} received:`, data);
}
}
// 使用
const subject = new Subject();
const observer1 = new Observer('观察者 1');
const observer2 = new Observer('观察者 2');
subject.attach(observer1);
subject.attach(observer2);
subject.notify('Hello, observers!');
// 输出:
// 观察者 1 received: Hello, observers!
// 观察者 2 received: Hello, observers!
2. 实际应用:事件总线
kotlin
class EventBus {
constructor() {
this.events = {};
}
on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
}
off(event, callback) {
if (!this.events[event]) return;
if (callback) {
this.events[event] = this.events[event].filter(cb => cb !== callback);
} else {
this.events[event] = [];
}
}
emit(event, data) {
if (!this.events[event]) return;
this.events[event].forEach(callback => callback(data));
}
once(event, callback) {
const wrapper = (data) => {
callback(data);
this.off(event, wrapper);
};
this.on(event, wrapper);
}
}
// 使用
const eventBus = new EventBus();
// 订阅事件
eventBus.on('user:login', (user) => {
console.log('用户登录:', user);
});
eventBus.on('user:login', (user) => {
console.log('记录登录日志:', user);
});
// 触发事件
eventBus.emit('user:login', { id: 1, name: '张三' });
// 输出:
// 用户登录:{ id: 1, name: '张三' }
// 记录登录日志:{ id: 1, name: '张三' }
3. 实际应用:Vue 3 响应式系统
kotlin
class ReactiveSystem {
constructor() {
this.targetStack = [];
}
track(target, key) {
if (this.targetStack.length === 0) return;
const activeEffect = this.targetStack[this.targetStack.length - 1];
if (!this.reactiveMap) {
this.reactiveMap = new WeakMap();
}
if (!this.reactiveMap.has(target)) {
this.reactiveMap.set(target, new Map());
}
const depsMap = this.reactiveMap.get(target);
if (!depsMap.has(key)) {
depsMap.set(key, new Set());
}
depsMap.get(key).add(activeEffect);
}
trigger(target, key) {
if (!this.reactiveMap) return;
const depsMap = this.reactiveMap.get(target);
if (!depsMap) return;
const deps = depsMap.get(key);
if (!deps) return;
deps.forEach(effect => effect());
}
effect(fn) {
const effectFn = () => {
this.targetStack.push(effectFn);
fn();
this.targetStack.pop();
};
effectFn();
return effectFn;
}
}
// 使用
const system = new ReactiveSystem();
const state = { count: 0 };
system.effect(() => {
system.track(state, 'count');
console.log('当前计数:', state.count);
});
// 更新状态
state.count = 1;
system.trigger(state, 'count');
// 输出:
// 当前计数:0
// 当前计数:1
总结
今天我们一起学习了三种重要的设计模式:
- 单例模式:确保唯一实例,适用于全局状态管理、配置中心等场景
- 工厂模式:封装对象创建逻辑,提高代码灵活性和可扩展性
- 观察者模式:实现对象间的一对多依赖,是事件系统和响应式编程的基础
这些模式在前端开发中无处不在,理解它们能帮助你写出更优雅、可维护的代码。下篇我们将继续探讨策略模式 、装饰器模式 和代理模式。