一、为什么需要工厂?(什么时候用)
场景:你有一个基类 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):注册用写锁,创建用读锁。