返回首页

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中,由于语言的灵活性,设计模式的实现往往更加简洁和灵活。


下一步学习算法与数据结构