05-设计模式
分类:03-异步编程进阶
发布于:
阅读时间:163 分钟
JavaScript设计模式
📋 学习目标
- 理解设计模式的概念和重要性
- 掌握常用的创建型设计模式
- 学会使用结构型设计模式
- 理解行为型设计模式的实际应用
- 学会在JavaScript中实现各种设计模式
- 了解设计模式的适用场景和最佳实践
🎯 设计模式基础
1. 什么是设计模式
// 设计模式是在软件设计中常见问题的可重用解决方案
// 它们不是具体的类或代码,而是解决问题的模板和方法
// 优点:
// 1. 可重用性:模式可以在多个项目中使用
// 2. 表达力:模式提供了一套标准的术语
// 3. 可维护性:模式使代码更易于理解和修改
// 4. 可靠性:模式经过时间验证,是可靠的解决方案
// 设计模式的三大类型:
// 1. 创建型模式:处理对象创建机制
// 2. 结构型模式:处理类和对象的组合
// 3. 行为型模式:处理对象间的通信和职责分配
2. JavaScript中的设计模式特点
// JavaScript的动态特性使得设计模式的实现更加灵活
// 1. 原型链继承
// 2. 函数是一等公民
// 3. 对象字面量
// 4. 闭包
// 5. 动态类型
// 示例:简单的单例模式
const singleton = (function() {
let instance;
function createInstance() {
return {
name: 'Singleton Instance',
createdAt: new Date()
};
}
return {
getInstance: function() {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
console.log(singleton.getInstance() === singleton.getInstance()); // true
🏗️ 创建型模式
1. 单例模式(Singleton)
// 确保一个类只有一个实例,并提供全局访问点
// 基础实现
class Singleton {
constructor() {
if (Singleton.instance) {
return Singleton.instance;
}
this.data = 'Singleton Data';
Singleton.instance = this;
}
getData() {
return this.data;
}
setData(newData) {
this.data = newData;
}
}
const instance1 = new Singleton();
const instance2 = new Singleton();
console.log(instance1 === instance2); // true
// 实际应用:数据库连接池
class DatabaseConnection {
constructor() {
if (DatabaseConnection.instance) {
return DatabaseConnection.instance;
}
this.connections = [];
this.maxConnections = 10;
DatabaseConnection.instance = this;
}
getConnection() {
if (this.connections.length < this.maxConnections) {
const connection = {
id: Math.random(),
query: (sql) => `Executing: ${sql}`
};
this.connections.push(connection);
return connection;
}
throw new Error('No available connections');
}
releaseConnection(connection) {
const index = this.connections.indexOf(connection);
if (index > -1) {
this.connections.splice(index, 1);
}
}
}
const db = new DatabaseConnection();
const conn1 = db.getConnection();
const conn2 = db.getConnection();
2. 工厂模式(Factory)
// 创建对象的过程封装起来,不暴露创建逻辑给客户端
// 简单工厂模式
class Button {
constructor(color, size) {
this.color = color;
this.size = size;
}
render() {
return `<button style="color: ${this.color}; font-size: ${this.size}px">Click me</button>`;
}
}
class Input {
constructor(placeholder, type) {
this.placeholder = placeholder;
this.type = type;
}
render() {
return `<input type="${this.type}" placeholder="${this.placeholder}">`;
}
}
// 简单工厂
class UIElementFactory {
static createElement(type, options) {
switch(type) {
case 'button':
return new Button(options.color, options.size);
case 'input':
return new Input(options.placeholder, options.type);
default:
throw new Error(`Unknown element type: ${type}`);
}
}
}
// 使用工厂
const button = UIElementFactory.createElement('button', {
color: 'red',
size: 16
});
const input = UIElementFactory.createElement('input', {
placeholder: 'Enter your name',
type: 'text'
});
console.log(button.render());
console.log(input.render());
// 抽象工厂模式
class ThemeFactory {
createButton() {
throw new Error('Must implement createButton method');
}
createInput() {
throw new Error('Must implement createInput method');
}
}
class LightThemeFactory extends ThemeFactory {
createButton() {
return new Button('#333', 14);
}
createInput() {
return new Input('Light theme placeholder', 'text');
}
}
class DarkThemeFactory extends ThemeFactory {
createButton() {
return new Button('#fff', 14);
}
createInput() {
return new Input('Dark theme placeholder', 'text');
}
}
// 使用抽象工厂
const lightFactory = new LightThemeFactory();
const darkFactory = new DarkThemeFactory();
const lightButton = lightFactory.createButton();
const darkButton = darkFactory.createButton();
3. 建造者模式(Builder)
// 分步构建复杂对象,允许同样的构建过程创建不同的表示
class ComputerBuilder {
constructor() {
this.reset();
}
reset() {
this.computer = {
cpu: '',
ram: '',
storage: '',
gpu: '',
price: 0
};
}
setCPU(cpu) {
this.computer.cpu = cpu;
this.computer.price += this.getCPUPrice(cpu);
return this;
}
setRAM(ram) {
this.computer.ram = ram;
this.computer.price += this.getRAMPrice(ram);
return this;
}
setStorage(storage) {
this.computer.storage = storage;
this.computer.price += this.getStoragePrice(storage);
return this;
}
setGPU(gpu) {
this.computer.gpu = gpu;
this.computer.price += this.getGPUPrice(gpu);
return this;
}
getCPUPrice(cpu) {
const prices = {
'i5': 200,
'i7': 350,
'i9': 500
};
return prices[cpu] || 0;
}
getRAMPrice(ram) {
const prices = {
'8GB': 50,
'16GB': 100,
'32GB': 200
};
return prices[ram] || 0;
}
getStoragePrice(storage) {
const prices = {
'256GB SSD': 60,
'512GB SSD': 100,
'1TB SSD': 200
};
return prices[storage] || 0;
}
getGPUPrice(gpu) {
const prices = {
'GTX 1660': 200,
'RTX 3060': 400,
'RTX 3070': 600
};
return prices[gpu] || 0;
}
build() {
const result = this.computer;
this.reset();
return result;
}
}
// 使用建造者
const builder = new ComputerBuilder();
const gamingPC = builder
.setCPU('i9')
.setRAM('32GB')
.setStorage('1TB SSD')
.setGPU('RTX 3070')
.build();
console.log(gamingPC);
// { cpu: 'i9', ram: '32GB', storage: '1TB SSD', gpu: 'RTX 3070', price: 1500 }
const officePC = builder
.setCPU('i5')
.setRAM('8GB')
.setStorage('256GB SSD')
.build();
console.log(officePC);
// { cpu: 'i5', ram: '8GB', storage: '256GB SSD', gpu: '', price: 310 }
🔧 结构型模式
1. 适配器模式(Adapter)
// 将一个类的接口转换成客户端希望的另一个接口
// 现有的接口
class LegacyWeatherService {
getWeatherData() {
return {
temperature: 25,
humidity: 60,
pressure: 1013,
windSpeed: 10
};
}
}
// 新的期望接口
class ModernWeatherService {
getTemperature() {
throw new Error('Must implement getTemperature');
}
getHumidity() {
throw new Error('Must implement getHumidity');
}
getWeatherSummary() {
throw new Error('Must implement getWeatherSummary');
}
}
// 适配器
class WeatherAdapter extends ModernWeatherService {
constructor(legacyService) {
super();
this.legacyService = legacyService;
}
getTemperature() {
const data = this.legacyService.getWeatherData();
return `${data.temperature}°C`;
}
getHumidity() {
const data = this.legacyService.getWeatherData();
return `${data.humidity}%`;
}
getWeatherSummary() {
const data = this.legacyService.getWeatherData();
return {
temperature: `${data.temperature}°C`,
humidity: `${data.humidity}%`,
conditions: data.pressure > 1010 ? 'High Pressure' : 'Low Pressure',
wind: `${data.windSpeed} km/h`
};
}
}
// 使用适配器
const legacyService = new LegacyWeatherService();
const modernService = new WeatherAdapter(legacyService);
console.log(modernService.getTemperature()); // "25°C"
console.log(modernService.getWeatherSummary());
2. 装饰器模式(Decorator)
// 动态地给对象添加新的功能,而不改变其结构
// 基础组件
class TextComponent {
constructor(text) {
this.text = text;
}
render() {
return this.text;
}
}
// 装饰器基类
class TextDecorator {
constructor(textComponent) {
this.textComponent = textComponent;
}
render() {
return this.textComponent.render();
}
}
// 具体装饰器
class BoldDecorator extends TextDecorator {
render() {
return `<b>${this.textComponent.render()}</b>`;
}
}
class ItalicDecorator extends TextDecorator {
render() {
return `<i>${this.textComponent.render()}</i>`;
}
}
class ColorDecorator extends TextDecorator {
constructor(textComponent, color) {
super(textComponent);
this.color = color;
}
render() {
return `<span style="color: ${this.color}">${this.textComponent.render()}</span>`;
}
}
// 使用装饰器
const basicText = new TextComponent('Hello World');
const boldText = new BoldDecorator(basicText);
const italicBoldText = new ItalicDecorator(boldText);
const coloredText = new ColorDecorator(italicBoldText, 'red');
console.log(coloredText.render());
// <span style="color: red"><i><b>Hello World</b></i></span>
// 实际应用:功能增强
class UserService {
constructor() {
this.users = new Map();
}
addUser(user) {
this.users.set(user.id, user);
}
getUser(id) {
return this.users.get(id);
}
}
// 日志装饰器
class UserServiceWithLogging extends UserService {
constructor(baseService) {
super();
this.baseService = baseService;
}
addUser(user) {
console.log(`Adding user: ${user.name}`);
this.baseService.addUser(user);
console.log(`User ${user.name} added successfully`);
}
getUser(id) {
console.log(`Fetching user with id: ${id}`);
const user = this.baseService.getUser(id);
console.log(`User fetched: ${user ? user.name : 'Not found'}`);
return user;
}
}
// 缓存装饰器
class UserServiceWithCache extends UserService {
constructor(baseService) {
super();
this.baseService = baseService;
this.cache = new Map();
}
getUser(id) {
if (this.cache.has(id)) {
console.log(`Cache hit for user id: ${id}`);
return this.cache.get(id);
}
const user = this.baseService.getUser(id);
if (user) {
this.cache.set(id, user);
}
return user;
}
}
3. 代理模式(Proxy)
// 为其他对象提供一种代理以控制对这个对象的访问
// 真实对象
class Image {
constructor(filename) {
this.filename = filename;
this.loadFromDisk();
}
loadFromDisk() {
console.log(`Loading image: ${this.filename}`);
this.data = `Image data for ${this.filename}`;
}
display() {
console.log(`Displaying: ${this.filename}`);
}
}
// 代理对象
class ImageProxy {
constructor(filename) {
this.filename = filename;
this.image = null;
}
display() {
if (!this.image) {
this.image = new Image(this.filename);
}
this.image.display();
}
}
// 使用代理(延迟加载)
const imageProxy1 = new ImageProxy('image1.jpg');
const imageProxy2 = new ImageProxy('image2.jpg');
console.log('Images loaded:');
// 只有当display被调用时才真正加载图片
imageProxy1.display(); // Loading image: image1.jpg, Displaying: image1.jpg
imageProxy2.display(); // Loading image: image2.jpg, Displaying: image2.jpg
// 实际应用:数据验证和缓存
const star = {
name: "张翠",
workPrice: 10000,
contact: "13800138000"
};
const proxy = new Proxy(star, {
get(target, key) {
if (key =<mark> "workPrice") {
console.log("访问了价格信息");
}
return target[key];
},
set(target, key, value) {
if (key </mark>= "workPrice") {
console.log("设置了价格信息");
if (value > 1000) {
console.log("价格合适,可以合作");
target[key] = value;
} else {
throw new Error("价钱不合适,拒绝合作");
}
} else if (key === "contact") {
// 验证手机号格式
if (/^1[3-9]\d{9}$/.test(value)) {
target[key] = value;
} else {
throw new Error("手机号格式不正确");
}
} else {
target[key] = value;
}
}
});
// 使用代理
console.log(proxy.workPrice); // 访问了价格信息, 10000
proxy.workPrice = 15000; // 设置了价格信息, 价格合适,可以合作
// proxy.workPrice = 500; // Error: 价钱不合适,拒绝合作
🎭 行为型模式
1. 策略模式(Strategy)
// 定义一系列算法,把它们一个个封装起来,并且使它们可相互替换
// 原始的硬编码实现
function calBonus(level, salary) {
if (level <mark> "A") {
return salary * 4;
}
if (level </mark> "B") {
return salary * 3;
}
if (level == "C") {
return salary * 2;
}
}
// 策略模式实现
const bonusStrategies = {
"A": (salary) => salary * 4,
"B": (salary) => salary * 3,
"C": (salary) => salary * 2
};
function calculateBonus(level, salary) {
const strategy = bonusStrategies[level];
if (!strategy) {
throw new Error(`Unknown level: ${level}`);
}
return strategy(salary);
}
// 实际应用:表单验证
class ValidationStrategy {
validate(value) {
throw new Error('Must implement validate method');
}
}
class RequiredStrategy extends ValidationStrategy {
validate(value) {
return value !<mark> null && value !</mark> undefined && value !== '';
}
}
class EmailStrategy extends ValidationStrategy {
validate(value) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
}
}
class MinLengthStrategy extends ValidationStrategy {
constructor(minLength) {
super();
this.minLength = minLength;
}
validate(value) {
return value && value.length >= this.minLength;
}
}
class Validator {
constructor() {
this.strategies = [];
}
addStrategy(strategy, message) {
this.strategies.push({ strategy, message });
}
validate(value) {
for (const { strategy, message } of this.strategies) {
if (!strategy.validate(value)) {
return message;
}
}
return null;
}
}
// 使用策略模式验证
const emailValidator = new Validator();
emailValidator.addStrategy(new RequiredStrategy(), '邮箱不能为空');
emailValidator.addStrategy(new EmailStrategy(), '邮箱格式不正确');
const passwordValidator = new Validator();
passwordValidator.addStrategy(new RequiredStrategy(), '密码不能为空');
passwordValidator.addStrategy(new MinLengthStrategy(8), '密码长度不能少于8位');
console.log(emailValidator.validate('user@example.com')); // null (验证通过)
console.log(emailValidator.validate('invalid-email')); // 邮箱格式不正确
console.log(passwordValidator.validate('123')); // 密码长度不能少于8位
// 实际应用:状态显示
const orderList = [
{ title: "订单1", type: 2 },
{ title: "订单2", type: 3 },
{ title: "订单3", type: 1 }
];
const statusStrategy = {
1: {
content: "审核中",
className: "yellow-item"
},
2: {
content: "已通过",
className: "green-item"
},
3: {
content: "被驳回",
className: "red-item"
}
};
function renderOrderList(orders) {
return orders.map(order => {
const status = statusStrategy[order.type];
return `
<li>
<div>${order.title}</div>
<div class="${status.className}">
${status.content}
</div>
</li>
`;
}).join('');
}
console.log(renderOrderList(orderList));
2. 观察者模式(Observer)
// 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,
// 所有依赖于它的对象都得到通知并被自动更新
// 观察者目标
class Subject {
constructor() {
this.observers = [];
}
subscribe(observer) {
this.observers.push(observer);
}
unsubscribe(observer) {
const index = this.observers.indexOf(observer);
if (index > -1) {
this.observers.splice(index, 1);
}
}
notify(data) {
this.observers.forEach(observer => observer.update(data));
}
}
// 具体观察者
class Observer {
constructor(name) {
this.name = name;
}
update(data) {
console.log(`${this.name} received update:`, data);
}
}
// 使用观察者模式
const subject = new Subject();
const observer1 = new Observer('Observer 1');
const observer2 = new Observer('Observer 2');
subject.subscribe(observer1);
subject.subscribe(observer2);
subject.notify('Hello Observers!');
// Observer 1 received update: Hello Observers!
// Observer 2 received update: Hello Observers!
// 实际应用:事件总线
class EventBus {
constructor() {
this.events = {};
}
on(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = [];
}
this.events[eventName].push(callback);
}
off(eventName, callback) {
if (this.events[eventName]) {
this.events[eventName] = this.events[eventName].filter(cb => cb !== callback);
}
}
emit(eventName, data) {
if (this.events[eventName]) {
this.events[eventName].forEach(callback => callback(data));
}
}
}
// 使用事件总线
const eventBus = new EventBus();
// 订阅用户登录事件
eventBus.on('userLogin', (user) => {
console.log(`用户 ${user.name} 登录了`);
// 显示欢迎消息
});
eventBus.on('userLogin', (user) => {
console.log(`发送欢迎邮件到 ${user.email}`);
// 发送邮件
});
// 触发用户登录事件
eventBus.emit('userLogin', {
name: '张三',
email: 'zhangsan@example.com'
});
// 实际应用:数据状态管理
class Store {
constructor() {
this.state = {
user: null,
cart: [],
products: []
};
this.listeners = [];
}
subscribe(listener) {
this.listeners.push(listener);
}
dispatch(action) {
switch(action.type) {
case 'SET_USER':
this.state.user = action.payload;
break;
case 'ADD_TO_CART':
this.state.cart.push(action.payload);
break;
case 'SET_PRODUCTS':
this.state.products = action.payload;
break;
}
this.notifyListeners();
}
notifyListeners() {
this.listeners.forEach(listener => listener(this.state));
}
getState() {
return this.state;
}
}
// 使用状态管理
const store = new Store();
// 订阅状态变化
store.subscribe((state) => {
console.log('State updated:', state);
// 更新UI
});
// 派发动作
store.dispatch({
type: 'SET_USER',
payload: { id: 1, name: 'John Doe' }
});
store.dispatch({
type: 'ADD_TO_CART',
payload: { id: 1, name: 'Product 1', price: 99.99 }
});
3. 发布订阅模式(Pub/Sub)
// 发布订阅模式是观察者模式的一种变体
// 发布者和订阅者完全解耦,通过事件总线进行通信
class PubSub {
constructor() {
this.events = {};
}
subscribe(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
}
unsubscribe(event, callback) {
if (this.events[event]) {
this.events[event] = this.events[event].filter(cb => cb !== callback);
}
}
publish(event, data) {
if (this.events[event]) {
this.events[event].forEach(callback => callback(data));
}
}
}
// 使用发布订阅模式
const pubSub = new PubSub();
// 订阅事件
pubSub.subscribe('news', (newsItem) => {
console.log('新闻订阅者收到:', newsItem);
});
pubSub.subscribe('sports', (sportsItem) => {
console.log('体育订阅者收到:', sportsItem);
});
// 发布事件
pubSub.publish('news', {
title: '重大新闻',
content: '今日要闻内容'
});
pubSub.publish('sports', {
title: '体育赛事',
content: '比赛结果'
});
4. 命令模式(Command)
// 将请求封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象
// 命令接口
class Command {
execute() {
throw new Error('Must implement execute method');
}
undo() {
throw new Error('Must implement undo method');
}
}
// 具体命令
class LightOnCommand extends Command {
constructor(light) {
super();
this.light = light;
}
execute() {
this.light.turnOn();
}
undo() {
this.light.turnOff();
}
}
class LightOffCommand extends Command {
constructor(light) {
super();
this.light = light;
}
execute() {
this.light.turnOff();
}
undo() {
this.light.turnOn();
}
}
// 接收者
class Light {
turnOn() {
console.log('Light is on');
}
turnOff() {
console.log('Light is off');
}
}
// 调用者
class RemoteControl {
constructor() {
this.command = null;
this.history = [];
}
setCommand(command) {
this.command = command;
}
pressButton() {
if (this.command) {
this.command.execute();
this.history.push(this.command);
}
}
pressUndo() {
if (this.history.length > 0) {
const lastCommand = this.history.pop();
lastCommand.undo();
}
}
}
// 使用命令模式
const light = new Light();
const lightOn = new LightOnCommand(light);
const lightOff = new LightOffCommand(light);
const remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton(); // Light is on
remote.setCommand(lightOff);
remote.pressButton(); // Light is off
remote.pressUndo(); // Light is on
🔄 模式组合应用
1. MVC模式(Model-View-Controller)
// Model - 数据模型
class TodoModel {
constructor() {
this.todos = [];
this.observers = [];
}
addObserver(observer) {
this.observers.push(observer);
}
notifyObservers() {
this.observers.forEach(observer => observer.update(this.todos));
}
addTodo(text) {
const todo = {
id: Date.now(),
text,
completed: false
};
this.todos.push(todo);
this.notifyObservers();
}
toggleTodo(id) {
const todo = this.todos.find(t => t.id === id);
if (todo) {
todo.completed = !todo.completed;
this.notifyObservers();
}
}
removeTodo(id) {
this.todos = this.todos.filter(t => t.id !== id);
this.notifyObservers();
}
}
// View - 视图
class TodoView {
constructor() {
this.todoList = document.getElementById('todo-list');
this.todoInput = document.getElementById('todo-input');
this.addButton = document.getElementById('add-button');
}
render(todos) {
this.todoList.innerHTML = todos.map(todo => `
<li class="${todo.completed ? 'completed' : ''}" data-id="${todo.id}">
<span>${todo.text}</span>
<button class="toggle">Toggle</button>
<button class="delete">Delete</button>
</li>
`).join('');
}
bindAddTodo(handler) {
this.addButton.addEventListener('click', () => {
handler(this.todoInput.value);
this.todoInput.value = '';
});
}
bindToggleTodo(handler) {
this.todoList.addEventListener('click', (e) => {
if (e.target.classList.contains('toggle')) {
const id = parseInt(e.target.parentElement.dataset.id);
handler(id);
}
});
}
bindDeleteTodo(handler) {
this.todoList.addEventListener('click', (e) => {
if (e.target.classList.contains('delete')) {
const id = parseInt(e.target.parentElement.dataset.id);
handler(id);
}
});
}
}
// Controller - 控制器
class TodoController {
constructor(model, view) {
this.model = model;
this.view = view;
this.model.addObserver(this);
this.view.bindAddTodo(this.handleAddTodo.bind(this));
this.view.bindToggleTodo(this.handleToggleTodo.bind(this));
this.view.bindDeleteTodo(this.handleDeleteTodo.bind(this));
}
update(todos) {
this.view.render(todos);
}
handleAddTodo(text) {
if (text.trim()) {
this.model.addTodo(text);
}
}
handleToggleTodo(id) {
this.model.toggleTodo(id);
}
handleDeleteTodo(id) {
this.model.removeTodo(id);
}
}
// 使用MVC模式
const model = new TodoModel();
const view = new TodoView();
const controller = new TodoController(model, view);
2. Repository模式
// Repository模式:数据访问层的抽象
class BaseRepository {
constructor() {
this.data = new Map();
}
findById(id) {
return this.data.get(id);
}
findAll() {
return Array.from(this.data.values());
}
save(entity) {
this.data.set(entity.id, entity);
return entity;
}
delete(id) {
this.data.delete(id);
}
}
class UserRepository extends BaseRepository {
findByEmail(email) {
return this.findAll().find(user => user.email === email);
}
findByName(name) {
return this.findAll().filter(user =>
user.name.toLowerCase().includes(name.toLowerCase())
);
}
findActiveUsers() {
return this.findAll().filter(user => user.isActive);
}
}
// 使用Repository模式
class UserService {
constructor() {
this.userRepository = new UserRepository();
}
createUser(userData) {
const user = {
id: Date.now(),
...userData,
isActive: true,
createdAt: new Date()
};
return this.userRepository.save(user);
}
getUserByEmail(email) {
return this.userRepository.findByEmail(email);
}
getActiveUsers() {
return this.userRepository.findActiveUsers();
}
deactivateUser(userId) {
const user = this.userRepository.findById(userId);
if (user) {
user.isActive = false;
this.userRepository.save(user);
}
return user;
}
}
🎯 模式选择指南
1. 选择合适的设计模式
// 模式选择决策树
const designPatternGuide = {
// 创建对象时
creation: {
needSingleInstance: 'Singleton',
needComplexObjectConstruction: 'Builder',
needObjectFamilies: 'Abstract Factory',
needObjectCreationWithoutSpecifyingClass: 'Factory Method'
},
// 组织对象和类时
structure: {
needInterfaceAdaptation: 'Adapter',
needRuntimeObjectEnhancement: 'Decorator',
needAccessControl: 'Proxy',
needSimplifiedInterface: 'Facade',
needObjectComposition: 'Composite'
},
// 对象间通信时
behavior: {
needAlgorithmVariation: 'Strategy',
needStateChangeNotification: 'Observer',
needObjectStateBasedBehavior: 'State',
needRequestEncapsulation: 'Command',
needSequentialAccess: 'Iterator'
}
};
2. 模式组合的最佳实践
// 示例:策略模式 + 工厂模式 + 观察者模式
class NotificationStrategy {
send(message, recipient) {
throw new Error('Must implement send method');
}
}
class EmailNotification extends NotificationStrategy {
send(message, recipient) {
console.log(`Email sent to ${recipient}: ${message}`);
// 实际发送邮件逻辑
}
}
class SMSNotification extends NotificationStrategy {
send(message, recipient) {
console.log(`SMS sent to ${recipient}: ${message}`);
// 实际发送短信逻辑
}
}
class PushNotification extends NotificationStrategy {
send(message, recipient) {
console.log(`Push notification sent to ${recipient}: ${message}`);
// 实际发送推送逻辑
}
}
// 工厂模式创建通知策略
class NotificationFactory {
static create(type) {
switch(type) {
case 'email':
return new EmailNotification();
case 'sms':
return new SMSNotification();
case 'push':
return new PushNotification();
default:
throw new Error(`Unknown notification type: ${type}`);
}
}
}
// 观察者模式通知多个接收者
class NotificationService {
constructor() {
this.subscribers = [];
}
subscribe(subscriber) {
this.subscribers.push(subscriber);
}
notifyAll(message, type = 'email') {
const strategy = NotificationFactory.create(type);
this.subscribers.forEach(subscriber => {
strategy.send(message, subscriber.contactInfo);
});
}
}
// 使用组合模式
const notificationService = new NotificationService();
notificationService.subscribe({
name: 'User 1',
contactInfo: 'user1@example.com'
});
notificationService.subscribe({
name: 'User 2',
contactInfo: 'user2@example.com'
});
notificationService.notifyAll('Hello Users!', 'email');
⚠️ 设计模式的陷阱
1. 过度设计
// ❌ 过度设计:为简单问题使用复杂模式
// 问题:只需要一个简单的计数器
class CounterSingletonFactoryProxyAdapterObserver {
// 这太复杂了!
constructor() {
this.count = 0;
}
increment() {
this.count++;
}
getCount() {
return this.count;
}
}
// ✅ 简单解决方案
class SimpleCounter {
constructor() {
this.count = 0;
}
increment() {
this.count++;
}
getCount() {
return this.count;
}
}
2. 误用模式
// ❌ 错误:在不需要的地方使用单例
class DatabaseConnection {
constructor() {
// 数据库连接应该是可配置的,不应该强制单例
this.connectionString = 'fixed-connection-string';
}
}
// ✅ 正确:使用依赖注入
class DatabaseConnection {
constructor(connectionString) {
this.connectionString = connectionString;
}
}
class DatabaseConnectionPool {
constructor() {
this.connections = new Map();
}
getConnection(connectionString) {
if (!this.connections.has(connectionString)) {
this.connections.set(connectionString,
new DatabaseConnection(connectionString));
}
return this.connections.get(connectionString);
}
}
3. 性能考虑
// ❌ 性能问题:频繁创建装饰器对象
function processItems(items) {
return items.map(item => {
return new LoggingDecorator(
new ValidationDecorator(
new CacheDecorator(item)
)
);
});
}
// ✅ 性能优化:重用装饰器或使用组合
class ItemProcessor {
constructor() {
this.logger = new Logger();
this.validator = new Validator();
this.cache = new Cache();
}
process(item) {
this.validator.validate(item);
this.logger.log(`Processing item: ${item.id}`);
return this.cache.getOrSet(item.id, () => this.doProcess(item));
}
doProcess(item) {
// 实际处理逻辑
return processedItem;
}
}
📝 最佳实践
1. 设计模式使用原则
// 1. 单一职责原则
class UserService {
// 只负责用户相关操作
createUser(userData) { /* ... */ }
updateUser(id, data) { /* ... */ }
deleteUser(id) { /* ... */ }
}
class UserValidator {
// 只负责用户验证
validate(userData) { /* ... */ }
}
// 2. 开闭原则
class NotificationService {
// 对扩展开放,对修改关闭
sendNotification(notification) {
notification.send();
}
}
// 3. 依赖倒置原则
class UserController {
constructor(notificationService, userRepository) {
this.notificationService = notificationService; // 依赖抽象,不是具体实现
this.userRepository = userRepository;
}
}
2. 模式实现建议
// 1. 优先使用组合而不是继承
class Car {
constructor(engine, wheels) {
this.engine = engine; // 组合
this.wheels = wheels; // 组合
}
}
// 2. 保持接口简单
class PaymentProcessor {
processPayment(amount, method) {
// 简单的接口,内部可能使用复杂的策略模式
const strategy = this.getStrategy(method);
return strategy.process(amount);
}
}
// 3. 考虑可测试性
class UserService {
constructor(userRepository, emailService) { // 依赖注入
this.userRepository = userRepository;
this.emailService = emailService;
}
async registerUser(userData) {
const user = await this.userRepository.save(userData);
await this.emailService.sendWelcomeEmail(user.email);
return user;
}
}
🎯 小结
- 理解了设计模式的概念和三大类型(创建型、结构型、行为型)
- 掌握了常用的设计模式及其JavaScript实现
- 学会了在实际项目中应用设计模式
- 了解了设计模式的组合使用和最佳实践
- 认识到过度设计的陷阱和性能考虑
- 学会了选择合适设计模式的方法
设计模式是软件开发中的重要工具,但关键是要根据实际需求选择合适的模式,避免过度设计。在JavaScript中,由于语言的灵活性,设计模式的实现往往更加简洁和灵活。
下一步学习:算法与数据结构