Skip to content

JavaScript工厂模式2024:前端开发者掌握工厂设计模式的完整指南

📊 SEO元描述:2024年最新JavaScript工厂模式教程,详解简单工厂模式、工厂方法模式、抽象工厂模式。包含完整实战案例,适合前端开发者掌握创建型设计模式。

核心关键词:JavaScript工厂模式2024、工厂设计模式、简单工厂模式、工厂方法模式、抽象工厂模式、JavaScript设计模式

长尾关键词:JavaScript工厂模式怎么实现、工厂模式应用场景、JavaScript设计模式最佳实践、前端工厂模式优缺点、抽象工厂模式实现


📚 JavaScript工厂模式学习目标与核心收获

通过本节JavaScript工厂模式完整指南,你将系统性掌握:

  • 工厂模式核心概念:深入理解工厂模式的定义、特点和设计原则
  • 三种工厂模式精通:掌握简单工厂、工厂方法、抽象工厂三种模式的实现
  • 应用场景深度分析:学会识别和应用工厂模式的最佳使用场景
  • 对象创建策略:掌握复杂对象创建的封装和管理技巧
  • 扩展性设计:理解工厂模式在系统扩展性方面的优势
  • 实战项目应用:在真实项目中正确应用工厂模式解决实际问题

🎯 适合人群

  • 前端开发工程师希望掌握对象创建的高级技巧和设计模式
  • JavaScript高级开发者需要深入理解面向对象编程和架构设计
  • 技术负责人关注代码架构的可扩展性和可维护性
  • 全栈开发者想要提升软件设计和系统架构能力

🌟 什么是工厂模式?为什么工厂模式如此重要?

工厂模式是什么?这是创建型设计模式中最重要的模式之一。工厂模式(Factory Pattern)是指通过工厂类来创建对象,而不是直接使用new操作符创建对象的设计模式,也是面向对象编程中封装对象创建逻辑的核心技术。

工厂模式的核心价值

  • 🎯 创建封装:将对象创建逻辑封装在工厂中,隐藏创建细节
  • 🔧 解耦合:客户端代码与具体类解耦,提高代码灵活性
  • 💡 扩展性:新增产品类型时无需修改现有代码
  • 📚 统一管理:集中管理对象创建逻辑,便于维护和优化
  • 🚀 多态支持:支持运行时决定创建哪种类型的对象

💡 设计模式建议:工厂模式是解决对象创建复杂性的最佳方案,特别适用于需要根据条件创建不同类型对象的场景。

简单工厂模式:基础的对象创建封装

简单工厂模式通过一个工厂类根据参数创建不同类型的对象,是最基础的工厂模式实现。

javascript
// 🎉 简单工厂模式实现

// 产品基类
class Shape {
    constructor(type) {
        this.type = type;
    }
    
    draw() {
        throw new Error('draw method must be implemented');
    }
    
    getArea() {
        throw new Error('getArea method must be implemented');
    }
    
    getInfo() {
        return {
            type: this.type,
            area: this.getArea()
        };
    }
}

// 具体产品类
class Circle extends Shape {
    constructor(radius) {
        super('Circle');
        this.radius = radius;
    }
    
    draw() {
        console.log(`Drawing a circle with radius ${this.radius}`);
        return `<circle r="${this.radius}" />`;
    }
    
    getArea() {
        return Math.PI * this.radius * this.radius;
    }
}

class Rectangle extends Shape {
    constructor(width, height) {
        super('Rectangle');
        this.width = width;
        this.height = height;
    }
    
    draw() {
        console.log(`Drawing a rectangle ${this.width}x${this.height}`);
        return `<rect width="${this.width}" height="${this.height}" />`;
    }
    
    getArea() {
        return this.width * this.height;
    }
}

class Triangle extends Shape {
    constructor(base, height) {
        super('Triangle');
        this.base = base;
        this.height = height;
    }
    
    draw() {
        console.log(`Drawing a triangle with base ${this.base} and height ${this.height}`);
        return `<polygon points="0,${this.height} ${this.base/2},0 ${this.base},${this.height}" />`;
    }
    
    getArea() {
        return (this.base * this.height) / 2;
    }
}

// 简单工厂类
class ShapeFactory {
    static createShape(type, ...args) {
        switch (type.toLowerCase()) {
            case 'circle':
                return new Circle(args[0]);
            case 'rectangle':
                return new Rectangle(args[0], args[1]);
            case 'triangle':
                return new Triangle(args[0], args[1]);
            default:
                throw new Error(`Unknown shape type: ${type}`);
        }
    }
    
    // 支持配置对象的创建方式
    static createShapeFromConfig(config) {
        const { type, ...params } = config;
        
        switch (type.toLowerCase()) {
            case 'circle':
                return new Circle(params.radius);
            case 'rectangle':
                return new Rectangle(params.width, params.height);
            case 'triangle':
                return new Triangle(params.base, params.height);
            default:
                throw new Error(`Unknown shape type: ${type}`);
        }
    }
    
    // 批量创建
    static createShapes(configs) {
        return configs.map(config => this.createShapeFromConfig(config));
    }
    
    // 获取支持的形状类型
    static getSupportedTypes() {
        return ['circle', 'rectangle', 'triangle'];
    }
    
    // 验证配置
    static validateConfig(config) {
        const { type } = config;
        
        if (!type) {
            throw new Error('Shape type is required');
        }
        
        if (!this.getSupportedTypes().includes(type.toLowerCase())) {
            throw new Error(`Unsupported shape type: ${type}`);
        }
        
        switch (type.toLowerCase()) {
            case 'circle':
                if (!config.radius || config.radius <= 0) {
                    throw new Error('Circle requires a positive radius');
                }
                break;
            case 'rectangle':
                if (!config.width || !config.height || config.width <= 0 || config.height <= 0) {
                    throw new Error('Rectangle requires positive width and height');
                }
                break;
            case 'triangle':
                if (!config.base || !config.height || config.base <= 0 || config.height <= 0) {
                    throw new Error('Triangle requires positive base and height');
                }
                break;
        }
        
        return true;
    }
}

// 高级简单工厂 - 支持插件式扩展
class AdvancedShapeFactory {
    constructor() {
        this.creators = new Map();
        this.validators = new Map();
        
        // 注册默认创建器
        this.registerCreator('circle', (config) => new Circle(config.radius));
        this.registerCreator('rectangle', (config) => new Rectangle(config.width, config.height));
        this.registerCreator('triangle', (config) => new Triangle(config.base, config.height));
        
        // 注册默认验证器
        this.registerValidator('circle', (config) => {
            if (!config.radius || config.radius <= 0) {
                throw new Error('Circle requires a positive radius');
            }
        });
        
        this.registerValidator('rectangle', (config) => {
            if (!config.width || !config.height || config.width <= 0 || config.height <= 0) {
                throw new Error('Rectangle requires positive width and height');
            }
        });
        
        this.registerValidator('triangle', (config) => {
            if (!config.base || !config.height || config.base <= 0 || config.height <= 0) {
                throw new Error('Triangle requires positive base and height');
            }
        });
    }
    
    registerCreator(type, creator) {
        this.creators.set(type.toLowerCase(), creator);
        return this;
    }
    
    registerValidator(type, validator) {
        this.validators.set(type.toLowerCase(), validator);
        return this;
    }
    
    createShape(config) {
        const type = config.type.toLowerCase();
        
        // 验证配置
        if (this.validators.has(type)) {
            this.validators.get(type)(config);
        }
        
        // 创建对象
        if (this.creators.has(type)) {
            return this.creators.get(type)(config);
        }
        
        throw new Error(`Unknown shape type: ${config.type}`);
    }
    
    getSupportedTypes() {
        return Array.from(this.creators.keys());
    }
    
    hasType(type) {
        return this.creators.has(type.toLowerCase());
    }
}

// 使用示例
console.log('=== 简单工厂模式测试 ===');

// 基础使用
const circle = ShapeFactory.createShape('circle', 5);
const rectangle = ShapeFactory.createShape('rectangle', 10, 8);
const triangle = ShapeFactory.createShape('triangle', 6, 4);

console.log('Circle area:', circle.getArea());
console.log('Rectangle area:', rectangle.getArea());
console.log('Triangle area:', triangle.getArea());

// 配置对象方式
const shapes = ShapeFactory.createShapes([
    { type: 'circle', radius: 3 },
    { type: 'rectangle', width: 5, height: 7 },
    { type: 'triangle', base: 8, height: 6 }
]);

shapes.forEach(shape => {
    console.log(shape.getInfo());
});

// 高级工厂使用
const advancedFactory = new AdvancedShapeFactory();

// 扩展新的形状类型
class Ellipse extends Shape {
    constructor(a, b) {
        super('Ellipse');
        this.a = a; // 长半轴
        this.b = b; // 短半轴
    }
    
    draw() {
        console.log(`Drawing an ellipse with semi-axes ${this.a} and ${this.b}`);
        return `<ellipse rx="${this.a}" ry="${this.b}" />`;
    }
    
    getArea() {
        return Math.PI * this.a * this.b;
    }
}

// 注册新类型
advancedFactory.registerCreator('ellipse', (config) => new Ellipse(config.a, config.b));
advancedFactory.registerValidator('ellipse', (config) => {
    if (!config.a || !config.b || config.a <= 0 || config.b <= 0) {
        throw new Error('Ellipse requires positive semi-axes a and b');
    }
});

const ellipse = advancedFactory.createShape({ type: 'ellipse', a: 4, b: 3 });
console.log('Ellipse info:', ellipse.getInfo());

简单工厂模式的特点

  • 集中创建:所有对象创建逻辑集中在一个工厂类中
  • 参数化创建:根据参数决定创建哪种类型的对象
  • 易于使用:客户端只需要知道产品名称即可创建对象
  • 扩展限制:新增产品类型需要修改工厂类代码

工厂方法模式:可扩展的对象创建

工厂方法模式通过抽象工厂类定义创建接口,具体工厂类实现创建逻辑,支持更好的扩展性。

javascript
// 🎉 工厂方法模式实现

// 抽象产品类
class Logger {
    constructor(name) {
        this.name = name;
        this.created = new Date();
    }
    
    log(level, message, ...args) {
        throw new Error('log method must be implemented');
    }
    
    info(message, ...args) {
        this.log('INFO', message, ...args);
    }
    
    warn(message, ...args) {
        this.log('WARN', message, ...args);
    }
    
    error(message, ...args) {
        this.log('ERROR', message, ...args);
    }
    
    debug(message, ...args) {
        this.log('DEBUG', message, ...args);
    }
}

// 具体产品类
class ConsoleLogger extends Logger {
    constructor(name, options = {}) {
        super(name);
        this.colorEnabled = options.colorEnabled !== false;
        this.timestampEnabled = options.timestampEnabled !== false;
    }
    
    log(level, message, ...args) {
        const timestamp = this.timestampEnabled ? 
            `[${new Date().toISOString()}] ` : '';
        const prefix = `${timestamp}[${level}] [${this.name}]`;
        
        if (this.colorEnabled) {
            const colors = {
                INFO: '\x1b[36m',    // cyan
                WARN: '\x1b[33m',    // yellow
                ERROR: '\x1b[31m',   // red
                DEBUG: '\x1b[90m'    // gray
            };
            const reset = '\x1b[0m';
            const color = colors[level] || '';
            
            console.log(`${color}${prefix}${reset}`, message, ...args);
        } else {
            console.log(prefix, message, ...args);
        }
    }
}

class FileLogger extends Logger {
    constructor(name, options = {}) {
        super(name);
        this.filename = options.filename || `${name}.log`;
        this.maxSize = options.maxSize || 10 * 1024 * 1024; // 10MB
        this.logs = [];
    }
    
    log(level, message, ...args) {
        const timestamp = new Date().toISOString();
        const logEntry = {
            timestamp,
            level,
            logger: this.name,
            message,
            args: args.length > 0 ? args : undefined
        };
        
        this.logs.push(logEntry);
        
        // 模拟写入文件
        this.writeToFile(logEntry);
        
        // 检查文件大小限制
        if (this.logs.length > 1000) {
            this.rotateLogs();
        }
    }
    
    writeToFile(logEntry) {
        // 在实际应用中,这里会写入到文件系统
        const logLine = `${logEntry.timestamp} [${logEntry.level}] [${logEntry.logger}] ${logEntry.message}`;
        console.log(`[FILE: ${this.filename}] ${logLine}`);
    }
    
    rotateLogs() {
        // 日志轮转逻辑
        const oldLogs = this.logs.splice(0, 500);
        console.log(`Rotated ${oldLogs.length} log entries from ${this.filename}`);
    }
    
    getLogs(level = null, limit = 100) {
        let filteredLogs = this.logs;
        
        if (level) {
            filteredLogs = this.logs.filter(log => log.level === level);
        }
        
        return filteredLogs.slice(-limit);
    }
}

class RemoteLogger extends Logger {
    constructor(name, options = {}) {
        super(name);
        this.endpoint = options.endpoint || '/api/logs';
        this.batchSize = options.batchSize || 10;
        this.flushInterval = options.flushInterval || 5000;
        this.buffer = [];
        
        this.startFlushTimer();
    }
    
    log(level, message, ...args) {
        const logEntry = {
            timestamp: new Date().toISOString(),
            level,
            logger: this.name,
            message,
            args: args.length > 0 ? args : undefined,
            userAgent: navigator.userAgent,
            url: window.location.href
        };
        
        this.buffer.push(logEntry);
        
        if (this.buffer.length >= this.batchSize) {
            this.flush();
        }
    }
    
    async flush() {
        if (this.buffer.length === 0) return;
        
        const logs = this.buffer.splice(0);
        
        try {
            await fetch(this.endpoint, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ logs })
            });
            
            console.log(`Sent ${logs.length} logs to remote server`);
        } catch (error) {
            console.error('Failed to send logs to remote server:', error);
            // 重新加入缓冲区
            this.buffer.unshift(...logs);
        }
    }
    
    startFlushTimer() {
        setInterval(() => {
            this.flush();
        }, this.flushInterval);
    }
}

// 抽象工厂类
class LoggerFactory {
    createLogger(name, options) {
        throw new Error('createLogger method must be implemented');
    }
    
    // 模板方法 - 提供通用的创建流程
    createLoggerWithValidation(name, options = {}) {
        this.validateName(name);
        this.validateOptions(options);
        
        const logger = this.createLogger(name, options);
        this.configureLogger(logger, options);
        
        return logger;
    }
    
    validateName(name) {
        if (!name || typeof name !== 'string') {
            throw new Error('Logger name must be a non-empty string');
        }
    }
    
    validateOptions(options) {
        if (options && typeof options !== 'object') {
            throw new Error('Logger options must be an object');
        }
    }
    
    configureLogger(logger, options) {
        // 通用配置逻辑
        if (options.level) {
            logger.level = options.level;
        }
    }
}

// 具体工厂类
class ConsoleLoggerFactory extends LoggerFactory {
    createLogger(name, options) {
        return new ConsoleLogger(name, options);
    }
}

class FileLoggerFactory extends LoggerFactory {
    createLogger(name, options) {
        return new FileLogger(name, options);
    }
    
    validateOptions(options) {
        super.validateOptions(options);
        
        if (options.filename && typeof options.filename !== 'string') {
            throw new Error('Filename must be a string');
        }
        
        if (options.maxSize && (typeof options.maxSize !== 'number' || options.maxSize <= 0)) {
            throw new Error('Max size must be a positive number');
        }
    }
}

class RemoteLoggerFactory extends LoggerFactory {
    createLogger(name, options) {
        return new RemoteLogger(name, options);
    }
    
    validateOptions(options) {
        super.validateOptions(options);
        
        if (options.endpoint && typeof options.endpoint !== 'string') {
            throw new Error('Endpoint must be a string');
        }
        
        if (options.batchSize && (typeof options.batchSize !== 'number' || options.batchSize <= 0)) {
            throw new Error('Batch size must be a positive number');
        }
    }
}

// 工厂管理器
class LoggerFactoryManager {
    constructor() {
        this.factories = new Map();
        this.defaultFactory = null;
        
        // 注册默认工厂
        this.registerFactory('console', new ConsoleLoggerFactory());
        this.registerFactory('file', new FileLoggerFactory());
        this.registerFactory('remote', new RemoteLoggerFactory());
        
        this.setDefaultFactory('console');
    }
    
    registerFactory(type, factory) {
        if (!(factory instanceof LoggerFactory)) {
            throw new Error('Factory must be an instance of LoggerFactory');
        }
        
        this.factories.set(type, factory);
        return this;
    }
    
    setDefaultFactory(type) {
        if (!this.factories.has(type)) {
            throw new Error(`Factory type '${type}' not registered`);
        }
        
        this.defaultFactory = type;
        return this;
    }
    
    createLogger(type, name, options) {
        const factoryType = type || this.defaultFactory;
        
        if (!this.factories.has(factoryType)) {
            throw new Error(`Unknown logger factory type: ${factoryType}`);
        }
        
        const factory = this.factories.get(factoryType);
        return factory.createLoggerWithValidation(name, options);
    }
    
    getSupportedTypes() {
        return Array.from(this.factories.keys());
    }
}

// 使用示例
console.log('=== 工厂方法模式测试 ===');

const loggerManager = new LoggerFactoryManager();

// 创建不同类型的日志记录器
const consoleLogger = loggerManager.createLogger('console', 'App', {
    colorEnabled: true,
    timestampEnabled: true
});

const fileLogger = loggerManager.createLogger('file', 'FileApp', {
    filename: 'app.log',
    maxSize: 5 * 1024 * 1024
});

const remoteLogger = loggerManager.createLogger('remote', 'RemoteApp', {
    endpoint: '/api/logs',
    batchSize: 5,
    flushInterval: 3000
});

// 使用日志记录器
consoleLogger.info('Application started');
consoleLogger.warn('This is a warning');
consoleLogger.error('This is an error');

fileLogger.info('File logging test');
fileLogger.debug('Debug information');

remoteLogger.info('Remote logging test');
remoteLogger.error('Remote error logging');

// 扩展新的日志记录器类型
class DatabaseLogger extends Logger {
    constructor(name, options = {}) {
        super(name);
        this.tableName = options.tableName || 'logs';
        this.connectionString = options.connectionString;
    }
    
    log(level, message, ...args) {
        const logEntry = {
            timestamp: new Date(),
            level,
            logger: this.name,
            message,
            args: JSON.stringify(args)
        };
        
        // 模拟数据库插入
        console.log(`[DB: ${this.tableName}] INSERT:`, logEntry);
    }
}

class DatabaseLoggerFactory extends LoggerFactory {
    createLogger(name, options) {
        return new DatabaseLogger(name, options);
    }
    
    validateOptions(options) {
        super.validateOptions(options);
        
        if (!options.connectionString) {
            throw new Error('Database connection string is required');
        }
    }
}

// 注册新的工厂类型
loggerManager.registerFactory('database', new DatabaseLoggerFactory());

const dbLogger = loggerManager.createLogger('database', 'DBApp', {
    connectionString: 'mongodb://localhost:27017/logs',
    tableName: 'application_logs'
});

dbLogger.info('Database logging test');

console.log('Supported logger types:', loggerManager.getSupportedTypes());

工厂方法模式的优势

  • 🎯 开闭原则:对扩展开放,对修改关闭
  • 🎯 单一职责:每个工厂只负责创建一种类型的对象
  • 🎯 多态性:通过抽象工厂接口实现多态
  • 🎯 可测试性:便于单元测试和模拟对象

抽象工厂模式:产品族的创建管理

抽象工厂模式提供创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

javascript
// 🎉 抽象工厂模式实现

// 抽象产品 - UI组件
class Button {
    constructor(text) {
        this.text = text;
    }
    
    render() {
        throw new Error('render method must be implemented');
    }
    
    onClick(handler) {
        this.clickHandler = handler;
    }
}

class Input {
    constructor(placeholder) {
        this.placeholder = placeholder;
        this.value = '';
    }
    
    render() {
        throw new Error('render method must be implemented');
    }
    
    setValue(value) {
        this.value = value;
    }
    
    getValue() {
        return this.value;
    }
}

class Modal {
    constructor(title, content) {
        this.title = title;
        this.content = content;
        this.isVisible = false;
    }
    
    render() {
        throw new Error('render method must be implemented');
    }
    
    show() {
        this.isVisible = true;
    }
    
    hide() {
        this.isVisible = false;
    }
}

// Material Design 产品族
class MaterialButton extends Button {
    render() {
        return `
            <button class="mdc-button mdc-button--raised" onclick="${this.clickHandler}">
                <span class="mdc-button__label">${this.text}</span>
            </button>
        `;
    }
}

class MaterialInput extends Input {
    render() {
        return `
            <div class="mdc-text-field mdc-text-field--filled">
                <span class="mdc-text-field__ripple"></span>
                <input class="mdc-text-field__input" type="text" 
                       placeholder="${this.placeholder}" value="${this.value}">
                <span class="mdc-line-ripple"></span>
            </div>
        `;
    }
}

class MaterialModal extends Modal {
    render() {
        return `
            <div class="mdc-dialog ${this.isVisible ? 'mdc-dialog--open' : ''}" role="alertdialog">
                <div class="mdc-dialog__container">
                    <div class="mdc-dialog__surface">
                        <h2 class="mdc-dialog__title">${this.title}</h2>
                        <div class="mdc-dialog__content">${this.content}</div>
                        <div class="mdc-dialog__actions">
                            <button type="button" class="mdc-button mdc-dialog__button">Close</button>
                        </div>
                    </div>
                </div>
                <div class="mdc-dialog__scrim"></div>
            </div>
        `;
    }
}

// Bootstrap 产品族
class BootstrapButton extends Button {
    render() {
        return `
            <button type="button" class="btn btn-primary" onclick="${this.clickHandler}">
                ${this.text}
            </button>
        `;
    }
}

class BootstrapInput extends Input {
    render() {
        return `
            <div class="form-group">
                <input type="text" class="form-control" 
                       placeholder="${this.placeholder}" value="${this.value}">
            </div>
        `;
    }
}

class BootstrapModal extends Modal {
    render() {
        return `
            <div class="modal fade ${this.isVisible ? 'show' : ''}" tabindex="-1" role="dialog">
                <div class="modal-dialog" role="document">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5 class="modal-title">${this.title}</h5>
                            <button type="button" class="close" data-dismiss="modal">
                                <span>&times;</span>
                            </button>
                        </div>
                        <div class="modal-body">${this.content}</div>
                        <div class="modal-footer">
                            <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                        </div>
                    </div>
                </div>
            </div>
        `;
    }
}

// Ant Design 产品族
class AntButton extends Button {
    render() {
        return `
            <button class="ant-btn ant-btn-primary" onclick="${this.clickHandler}">
                <span>${this.text}</span>
            </button>
        `;
    }
}

class AntInput extends Input {
    render() {
        return `
            <div class="ant-input-wrapper">
                <input class="ant-input" type="text" 
                       placeholder="${this.placeholder}" value="${this.value}">
            </div>
        `;
    }
}

class AntModal extends Modal {
    render() {
        return `
            <div class="ant-modal-wrap ${this.isVisible ? '' : 'ant-modal-hidden'}">
                <div class="ant-modal">
                    <div class="ant-modal-content">
                        <div class="ant-modal-header">
                            <div class="ant-modal-title">${this.title}</div>
                        </div>
                        <div class="ant-modal-body">${this.content}</div>
                        <div class="ant-modal-footer">
                            <button class="ant-btn">Cancel</button>
                            <button class="ant-btn ant-btn-primary">OK</button>
                        </div>
                    </div>
                </div>
                <div class="ant-modal-mask"></div>
            </div>
        `;
    }
}

// 抽象工厂
class UIFactory {
    createButton(text) {
        throw new Error('createButton method must be implemented');
    }
    
    createInput(placeholder) {
        throw new Error('createInput method must be implemented');
    }
    
    createModal(title, content) {
        throw new Error('createModal method must be implemented');
    }
    
    // 创建完整的表单
    createForm(config) {
        const form = {
            title: config.title,
            fields: [],
            buttons: [],
            modal: null
        };
        
        // 创建表单字段
        config.fields.forEach(field => {
            form.fields.push(this.createInput(field.placeholder));
        });
        
        // 创建按钮
        config.buttons.forEach(button => {
            form.buttons.push(this.createButton(button.text));
        });
        
        // 创建模态框(如果需要)
        if (config.modal) {
            form.modal = this.createModal(config.modal.title, config.modal.content);
        }
        
        return form;
    }
    
    // 获取主题信息
    getThemeInfo() {
        return {
            name: this.constructor.name.replace('Factory', ''),
            version: '1.0.0'
        };
    }
}

// 具体工厂
class MaterialUIFactory extends UIFactory {
    createButton(text) {
        return new MaterialButton(text);
    }
    
    createInput(placeholder) {
        return new MaterialInput(placeholder);
    }
    
    createModal(title, content) {
        return new MaterialModal(title, content);
    }
}

class BootstrapUIFactory extends UIFactory {
    createButton(text) {
        return new BootstrapButton(text);
    }
    
    createInput(placeholder) {
        return new BootstrapInput(placeholder);
    }
    
    createModal(title, content) {
        return new BootstrapModal(title, content);
    }
}

class AntUIFactory extends UIFactory {
    createButton(text) {
        return new AntButton(text);
    }
    
    createInput(placeholder) {
        return new AntInput(placeholder);
    }
    
    createModal(title, content) {
        return new AntModal(title, content);
    }
}

// 工厂选择器
class UIFactorySelector {
    constructor() {
        this.factories = new Map();
        this.currentTheme = 'material';
        
        // 注册工厂
        this.registerFactory('material', new MaterialUIFactory());
        this.registerFactory('bootstrap', new BootstrapUIFactory());
        this.registerFactory('ant', new AntUIFactory());
    }
    
    registerFactory(theme, factory) {
        if (!(factory instanceof UIFactory)) {
            throw new Error('Factory must be an instance of UIFactory');
        }
        
        this.factories.set(theme, factory);
        return this;
    }
    
    setTheme(theme) {
        if (!this.factories.has(theme)) {
            throw new Error(`Unknown theme: ${theme}`);
        }
        
        this.currentTheme = theme;
        return this;
    }
    
    getFactory(theme = null) {
        const selectedTheme = theme || this.currentTheme;
        
        if (!this.factories.has(selectedTheme)) {
            throw new Error(`Unknown theme: ${selectedTheme}`);
        }
        
        return this.factories.get(selectedTheme);
    }
    
    createComponent(type, ...args) {
        const factory = this.getFactory();
        
        switch (type) {
            case 'button':
                return factory.createButton(...args);
            case 'input':
                return factory.createInput(...args);
            case 'modal':
                return factory.createModal(...args);
            default:
                throw new Error(`Unknown component type: ${type}`);
        }
    }
    
    createForm(config, theme = null) {
        const factory = this.getFactory(theme);
        return factory.createForm(config);
    }
    
    getAvailableThemes() {
        return Array.from(this.factories.keys());
    }
    
    getCurrentTheme() {
        return this.currentTheme;
    }
}

// 使用示例
console.log('=== 抽象工厂模式测试 ===');

const uiSelector = new UIFactorySelector();

// 创建Material Design风格的组件
uiSelector.setTheme('material');
const materialButton = uiSelector.createComponent('button', 'Material Button');
const materialInput = uiSelector.createComponent('input', 'Enter your name');
const materialModal = uiSelector.createComponent('modal', 'Material Modal', 'This is a material modal');

console.log('Material Button HTML:', materialButton.render());
console.log('Material Input HTML:', materialInput.render());

// 创建Bootstrap风格的组件
uiSelector.setTheme('bootstrap');
const bootstrapButton = uiSelector.createComponent('button', 'Bootstrap Button');
const bootstrapInput = uiSelector.createComponent('input', 'Enter your email');

console.log('Bootstrap Button HTML:', bootstrapButton.render());
console.log('Bootstrap Input HTML:', bootstrapInput.render());

// 创建完整的表单
const formConfig = {
    title: 'User Registration',
    fields: [
        { placeholder: 'Enter your name' },
        { placeholder: 'Enter your email' },
        { placeholder: 'Enter your password' }
    ],
    buttons: [
        { text: 'Submit' },
        { text: 'Cancel' }
    ],
    modal: {
        title: 'Confirmation',
        content: 'Are you sure you want to submit?'
    }
};

// 使用不同主题创建表单
const materialForm = uiSelector.createForm(formConfig, 'material');
const bootstrapForm = uiSelector.createForm(formConfig, 'bootstrap');
const antForm = uiSelector.createForm(formConfig, 'ant');

console.log('Available themes:', uiSelector.getAvailableThemes());
console.log('Current theme:', uiSelector.getCurrentTheme());

// 渲染表单
console.log('Material form fields count:', materialForm.fields.length);
console.log('Bootstrap form buttons count:', bootstrapForm.buttons.length);
console.log('Ant form modal:', antForm.modal.render());

抽象工厂模式的优势

  • 🎯 产品族一致性:确保创建的产品属于同一个产品族
  • 🎯 易于切换:可以轻松切换整个产品族
  • 🎯 隔离具体类:客户端与具体产品类解耦
  • 🎯 符合开闭原则:新增产品族无需修改现有代码

💼 实际应用:抽象工厂模式在UI框架、主题系统、跨平台开发中应用广泛,如React的不同UI组件库、移动应用的iOS/Android适配等。


📚 JavaScript工厂模式学习总结与下一步规划

✅ 本节核心收获回顾

通过本节JavaScript工厂模式完整指南的学习,你已经掌握:

  1. 工厂模式核心概念:深入理解了工厂模式的定义、特点和设计原则
  2. 三种工厂模式精通:掌握了简单工厂、工厂方法、抽象工厂三种模式的实现
  3. 应用场景深度分析:学会了识别和应用工厂模式的最佳使用场景
  4. 对象创建策略:掌握了复杂对象创建的封装和管理技巧
  5. 扩展性设计:理解了工厂模式在系统扩展性方面的优势

🎯 工厂模式下一步

  1. 建造者模式学习:学习复杂对象的分步构建技术
  2. 依赖注入模式:了解现代框架中的依赖管理和对象创建
  3. 原型模式应用:掌握对象克隆和原型链的高级应用
  4. 组合模式设计:学习多个设计模式的组合使用

🔗 相关学习资源

  • 设计模式经典书籍:《Head First设计模式》、《设计模式之禅》
  • JavaScript高级编程:《JavaScript高级程序设计》、《你不知道的JavaScript》
  • 现代框架源码:React、Vue、Angular等框架中的工厂模式应用
  • 开源项目分析:学习优秀开源项目中的设计模式实践

💪 实践建议

  1. 重构现有代码:识别项目中可以应用工厂模式的场景并进行重构
  2. 设计新功能:在设计新功能时考虑使用工厂模式提升扩展性
  3. 性能测试:对比工厂模式和直接创建对象的性能差异
  4. 团队分享:与团队分享工厂模式的应用经验和最佳实践

🔍 常见问题FAQ

Q1: 什么时候应该使用工厂模式?

A: 当需要根据条件创建不同类型的对象、对象创建逻辑复杂、需要隐藏对象创建细节、或者需要支持系统扩展时,应该考虑使用工厂模式。

Q2: 简单工厂、工厂方法、抽象工厂有什么区别?

A: 简单工厂用一个工厂类创建所有产品;工厂方法为每种产品提供专门的工厂类;抽象工厂用于创建产品族,确保产品间的一致性。

Q3: 工厂模式会影响性能吗?

A: 工厂模式会增加一层抽象,可能带来轻微的性能开销,但这通常是可以接受的。相比直接创建对象,工厂模式提供的灵活性和可维护性更有价值。

Q4: 如何测试使用工厂模式的代码?

A: 可以通过模拟工厂、注入测试工厂、或者测试具体的产品类来进行测试。工厂模式实际上有助于提高代码的可测试性。

Q5: 工厂模式和单例模式可以结合使用吗?

A: 可以,工厂本身可以是单例的,确保全局只有一个工厂实例。这在需要统一管理对象创建逻辑时很有用。


🛠️ 工厂模式工具使用指南

常见问题解决方案

工厂注册机制

javascript
// 问题:动态注册新的产品类型
// 解决:实现插件式工厂注册

class PluginFactory {
    constructor() {
        this.creators = new Map();
        this.plugins = new Map();
    }
    
    registerPlugin(name, plugin) {
        this.plugins.set(name, plugin);
        
        if (plugin.creators) {
            Object.entries(plugin.creators).forEach(([type, creator]) => {
                this.creators.set(type, creator);
            });
        }
    }
    
    create(type, ...args) {
        if (this.creators.has(type)) {
            return this.creators.get(type)(...args);
        }
        throw new Error(`Unknown type: ${type}`);
    }
}

工厂缓存优化

javascript
// 问题:频繁创建相同对象导致性能问题
// 解决:实现工厂缓存机制

class CachedFactory {
    constructor() {
        this.cache = new Map();
        this.maxCacheSize = 100;
    }
    
    create(type, config) {
        const cacheKey = `${type}_${JSON.stringify(config)}`;
        
        if (this.cache.has(cacheKey)) {
            return this.cache.get(cacheKey);
        }
        
        const instance = this.createInstance(type, config);
        
        if (this.cache.size >= this.maxCacheSize) {
            const firstKey = this.cache.keys().next().value;
            this.cache.delete(firstKey);
        }
        
        this.cache.set(cacheKey, instance);
        return instance;
    }
}

"掌握工厂模式,让你的代码拥有更好的扩展性和可维护性。每一个设计模式的应用,都是对代码架构的提升!"