设计模式 | 工厂模式

发布于:2025-06-28 ⋅ 阅读:(15) ⋅ 点赞:(0)

工厂模式(Factory Pattern) 是创建型设计模式的核心成员,它通过将对象创建的逻辑封装起来,实现了创建与使用的解耦。本文将深入探讨工厂模式的核心思想、实现技巧以及在C++中的高效实现方式。

为什么需要工厂模式?

在软件开发中,直接使用new关键字创建对象会带来诸多问题:

  • 紧耦合:客户端代码依赖具体类实现

  • 难以扩展:添加新产品需要修改客户端代码

  • 职责混乱:对象创建逻辑分散在各处

  • 违反开闭原则:对修改开放,对扩展封闭

工厂模式通过封装对象创建过程解决了这些问题,提供了一种灵活的创建机制。当你的代码中存在以下情况时,工厂模式特别有用:

  • 无法预知需要创建的具体类型

  • 需要集中管理对象的创建逻辑

  • 系统需要支持多种类型的产品

  • 希望将实例化延迟到子类

工厂模式的两种形态

1. 简单工厂模式(静态工厂)

简单工厂模式是最基础的形式,它通过一个静态方法封装对象的创建逻辑。

#include <iostream>
#include <memory>
#include <stdexcept>

// 抽象产品类:图形接口
class Shape {
public:
    virtual void draw() const = 0;
    virtual ~Shape() = default;
};

// 具体产品类:圆形
class Circle : public Shape {
public:
    void draw() const override {
        std::cout << "○ 绘制圆形" << std::endl;
    }
};

// 具体产品类:矩形
class Rectangle : public Shape {
public:
    void draw() const override {
        std::cout << "□ 绘制矩形" << std::endl;
    }
};

// 具体产品类:三角形
class Triangle : public Shape {
public:
    void draw() const override {
        std::cout << "△ 绘制三角形" << std::endl;
    }
};

// 简单工厂类
class ShapeFactory {
public:
    // 形状类型枚举
    enum ShapeType { CIRCLE, RECTANGLE, TRIANGLE };
    
    // 创建形状的静态方法
    static std::unique_ptr<Shape> createShape(ShapeType type) {
        switch (type) {
            case CIRCLE:
                return std::make_unique<Circle>();
            case RECTANGLE:
                return std::make_unique<Rectangle>();
            case TRIANGLE:
                return std::make_unique<Triangle>();
            default:
                throw std::invalid_argument("错误:不支持的形状类型");
        }
    }
};

// 创建具体实列
int main() {
    // 创建圆形
    auto circle = ShapeFactory::createShape(ShapeFactory::CIRCLE);
    circle->draw();
    
    // 创建矩形
    auto rect = ShapeFactory::createShape(ShapeFactory::RECTANGLE);
    rect->draw();
    
    // 创建三角形
    auto triangle = ShapeFactory::createShape(ShapeFactory::TRIANGLE);
    triangle->draw();
    
    return 0;
}

优点

  • 实现简单,易于理解

  • 集中管理对象的创建逻辑

  • 客户端与具体产品类解耦

缺点

  • 违反开闭原则(添加新产品需修改工厂类)

  • 工厂类职责过重(所有产品都在一个工厂中创建)

  • 不支持运行时动态扩展

2. 工厂方法模式

工厂方法模式将对象创建延迟到子类,解决了简单工厂的开闭原则问题。

#include <iostream>
#include <memory>
#include <vector>

// 抽象产品:日志记录器
class Logger {
public:
    virtual void log(const std::string& message) = 0;
    virtual ~Logger() = default;
};

// 具体产品:文件日志
class FileLogger : public Logger {
public:
    void log(const std::string& message) override {
        std::cout << "[文件日志] " << message << std::endl;
    }
};

// 具体产品:控制台日志
class ConsoleLogger : public Logger {
public:
    void log(const std::string& message) override {
        std::cout << "[控制台日志] " << message << std::endl;
    }
};

// 具体产品:网络日志
class NetworkLogger : public Logger {
public:
    void log(const std::string& message) override {
        std::cout << "[网络日志] " << message << std::endl;
    }
};

// 抽象创建者
class LoggerCreator {
public:
    virtual std::unique_ptr<Logger> createLogger() = 0;
    
    void logMessage(const std::string& message) {
        auto logger = createLogger();
        logger->log(message);
    }
    
    virtual ~LoggerCreator() = default;
};

// 具体创建者:文件日志工厂
class FileLoggerCreator : public LoggerCreator {
public:
    std::unique_ptr<Logger> createLogger() override {
        return std::make_unique<FileLogger>();
    }
};

// 具体创建者:控制台日志工厂
class ConsoleLoggerCreator : public LoggerCreator {
public:
    std::unique_ptr<Logger> createLogger() override {
        return std::make_unique<ConsoleLogger>();
    }
};

// 具体创建者:网络日志工厂
class NetworkLoggerCreator : public LoggerCreator {
public:
    std::unique_ptr<Logger> createLogger() override {
        return std::make_unique<NetworkLogger>();
    }
};

// 创建实例
int main() {
    std::vector<std::unique_ptr<LoggerCreator>> creators;
    
    creators.push_back(std::make_unique<FileLoggerCreator>());
    creators.push_back(std::make_unique<ConsoleLoggerCreator>());
    creators.push_back(std::make_unique<NetworkLoggerCreator>());
    
    for (auto& creator : creators) {
        creator->logMessage("应用启动完成");
    }
    
    return 0;
}

核心思想

  • 定义创建对象的接口,但让子类决定实例化哪个类

  • 工厂方法使一个类的实例化延迟到其子类

  • 符合"开闭原则" - 对扩展开放,对修改关闭

工厂方法模式的高级应用

1. 参数化工厂方法

class UniversalCreator : public LoggerCreator {
public:
    enum LoggerType { FILE, CONSOLE, NETWORK };
    
    UniversalCreator(LoggerType type) : type_(type) {}
    
    std::unique_ptr<Logger> createLogger() override {
        switch (type_) {
            case FILE: return std::make_unique<FileLogger>();
            case CONSOLE: return std::make_unique<ConsoleLogger>();
            case NETWORK: return std::make_unique<NetworkLogger>();
            default: throw std::invalid_argument("无效的日志类型");
        }
    }

private:
    LoggerType type_;
};

// 使用示例
int main() {
    UniversalCreator fileCreator(UniversalCreator::FILE);
    fileCreator.logMessage("保存到文件");
    
    UniversalCreator consoleCreator(UniversalCreator::CONSOLE);
    consoleCreator.logMessage("输出到控制台");
    
    return 0;
}

2. 工厂方法 + 单例模式

class Database {
public:
    virtual void connect() = 0;
    virtual ~Database() = default;
};

class MySQL : public Database {
public:
    void connect() override {
        std::cout << "连接到MySQL数据库" << std::endl;
    }
    
    static MySQL& getInstance() {
        static MySQL instance;
        return instance;
    }
    
private:
    MySQL() = default;
};

class PostgreSQL : public Database {
public:
    void connect() override {
        std::cout << "连接到PostgreSQL数据库" << std::endl;
    }
    
    static PostgreSQL& getInstance() {
        static PostgreSQL instance;
        return instance;
    }
    
private:
    PostgreSQL() = default;
};

class DatabaseFactory {
public:
    virtual Database& create() = 0;
    virtual ~DatabaseFactory() = default;
};

class MySQLFactory : public DatabaseFactory {
public:
    Database& create() override {
        return MySQL::getInstance();
    }
};

class PostgreSQLFactory : public DatabaseFactory {
public:
    Database& create() override {
        return PostgreSQL::getInstance();
    }
};

// 使用示例
int main() {
    MySQLFactory mysqlFactory;
    auto& mysql = mysqlFactory.create();
    mysql.connect();
    
    PostgreSQLFactory pgFactory;
    auto& pg = pgFactory.create();
    pg.connect();
    
    return 0;
}

工厂模式的优缺点分析

优点

  • 解耦创建者和具体产品

  • 符合开闭原则,易于扩展

  • 单一职责原则(创建逻辑集中)

  • 便于代码维护和测试

  • 支持依赖倒置原则

缺点

  • 引入额外类,增加系统复杂性

  • 需要设计良好的继承体系

  • 客户端可能需要理解工厂结构

  • 简单场景下可能显得过度设计

工厂模式的典型应用场景

  1. 框架设计:框架需要为应用提供扩展点

    class Plugin {
    public:
        virtual void execute() = 0;
        virtual ~Plugin() = default;
    };
    
    class PluginFactory {
    public:
        virtual std::unique_ptr<Plugin> createPlugin() = 0;
    };
  2. 跨平台开发:为不同平台创建适配对象

    class GUIButton {
    public:
        virtual void render() = 0;
    };
    
    class WindowsButton : public GUIButton { /*...*/ };
    class MacButton : public GUIButton { /*...*/ };
    
    class GUIFactory {
    public:
        virtual std::unique_ptr<GUIButton> createButton() = 0;
    };
  3. 对象池管理:管理可重用对象的创建

    class Connection {
    public:
        virtual void open() = 0;
    };
    
    class ConnectionPool {
    public:
        virtual std::unique_ptr<Connection> createConnection() = 0;
        virtual void returnConnection(std::unique_ptr<Connection>) = 0;
    };
  4. 依赖注入:通过工厂注入依赖对象

    class Service {
    public:
        virtual void performTask() = 0;
    };
    
    class Client {
    public:
        Client(std::unique_ptr<ServiceFactory> factory)
            : factory_(std::move(factory)) {}
        
        void execute() {
            auto service = factory_->createService();
            service->performTask();
        }
    
    private:
        std::unique_ptr<ServiceFactory> factory_;
    };

工厂模式的最佳实践

  1. 优先使用工厂方法:除非系统非常简单,否则优先选择工厂方法模式

  2. 结合智能指针:使用std::unique_ptrstd::shared_ptr管理对象生命周期

  3. 使用模板减少重复代码

    template <typename T>
    class StandardCreator : public LoggerCreator {
    public:
        std::unique_ptr<Logger> createLogger() override {
            return std::make_unique<T>();
        }
    };
    
    // 使用
    StandardCreator<FileLogger> fileCreator;
  4. 工厂方法命名规范

  • createXXX()

  • makeXXX()

  • newXXX()

  • getInstance() (单例场景)

工厂模式 vs 简单工厂

特性 简单工厂模式 工厂方法模式
开闭原则 违反(修改工厂类) 支持(扩展子类)
复杂度 简单 中等
扩展性 有限 优秀
类数量 较少 较多(每个产品对应工厂)
适用场景 产品类型少且固定 产品类型多或可能扩展

总结

工厂模式是C++开发中强大的对象创建工具,通过封装对象的创建过程,它实现了:

  • 解耦:客户端代码与具体类实现分离

  • 扩展性:轻松添加新产品而不影响现有代码

  • 可维护性:集中管理创建逻辑

  • 灵活性:支持运行时决策和配置

在实际开发中,应当根据具体需求选择合适的工厂模式变体:

  • 对于简单场景,简单工厂足够高效

  • 对于需要高度扩展的系统,工厂方法是最佳选择

  • 避免过早优化,但为未来扩展留有余地

"设计模式不是银弹,而是工具箱中的工具。工厂模式是其中最常用且强大的工具之一。" - 设计模式实践者


网站公告

今日签到

点亮在社区的每一天
去签到