文档目录

一、为什么需要工厂?(什么时候用)

场景:你有一个基类 Product,多个派生类 ConcreteProductA / ConcreteProductB。客户端要创建产品,但不知道具体类型。

不用工厂:

std::unique_ptr<Product> createProduct(const std::string& type) {
    if (type == "A") return std::make_unique<ConcreteProductA>();
    if (type == "B") return std::make_unique<ConcreteProductB>();
    return nullptr;
}
// ↑ 每次加新产品都要改这个函数,违反了"开闭原则"

二、注册表工厂(最实用的工厂写法)

class ProductFactory {
    // 用 unique_ptr 返回,所有权清晰
    using Creator = std::function<std::unique_ptr<Product>()>;
    std::unordered_map<std::string, Creator> registry_;

public:
    void register_type(const std::string& type, Creator creator) {
        registry_[type] = std::move(creator);
    }

    std::unique_ptr<Product> create(const std::string& type) {
        auto it = registry_.find(type);
        if (it == registry_.end()) return nullptr;
        return it->second();  // 调用注册的创建函数
    }
};

// 使用
ProductFactory factory;
factory.register_type("Circle", [] { return std::make_unique<Circle>(); });
factory.register_type("Square", [] { return std::make_unique<Square>(); });

auto p = factory.create("Circle");  // unique_ptr<Product>

好处:

  • 加新产品不需要改工厂代码,只需要额外调用 register_type
  • unique_ptr 返回,调用者知道谁拥有对象

三、面试追问 Q&A

Q1:工厂返回 unique_ptr 还是 shared_ptr? A:工厂不应该替调用者决定所有权策略。返回 unique_ptr,调用者可以自由转换成 shared_ptr。如果工厂返回 shared_ptr,调用者想用 unique_ptr 却不行。

Q2:注册表工厂的线程安全性? A:注册阶段通常是单线程初始化。如果需要在运行时动态注册,加读写锁(std::shared_mutex):注册用写锁,创建用读锁。