在 C++ 中,设计高效的工厂通常涉及到以下几个关键方面:
- 使用注册表模式:注册表模式是一种将对象创建逻辑与对象实例化分离的技术。这可以让你在运行时动态地添加、删除或更改对象类型,而无需修改工厂代码。
- 利用智能指针:使用智能指针(如
std::unique_ptr
和std::shared_ptr
)可以自动管理内存,避免内存泄漏,并提供更好的异常安全性。 - 使用抽象基类:定义一个抽象基类,该类为所有要由工厂创建的对象类型提供通用接口。这样,你可以在不了解具体类型的情况下处理这些对象。
- 使用模板:模板可以帮助你编写更通用、更灵活的代码。例如,你可以使用模板函数来创建特定类型的对象,而无需为每种类型编写单独的工厂函数。
- 避免全局状态:尽量避免使用全局变量或单例来存储工厂状态。这可以让你更容易地测试和重用代码。
- 使用依赖注入:依赖注入是一种将对象的依赖项(如工厂)传递给它们所需的对象的技术。这可以让你更容易地测试和重用代码,因为你可以在不修改对象代码的情况下更改其依赖项。
- 保持简洁和可维护:确保你的工厂代码简洁、易于理解和维护。避免过度设计和不必要的复杂性。
以下是一个简单的示例,展示了如何使用注册表模式和智能指针实现高效的工厂:
#include
#include
#include
#include
// 抽象基类
class Shape {
public:
virtual ~Shape() = default;
virtual void draw() const = 0;
};
// 具体类
class Circle : public Shape {
public:
void draw() const override {
std::cout << "Drawing a circle"<< std::endl;
}
};
class Rectangle : public Shape {
public:
void draw() const override {
std::cout << "Drawing a rectangle"<< std::endl;
}
};
// 工厂类
class ShapeFactory {
public:
using ShapeCreator = std::function()>;
static void registerShape(const std::string& name, ShapeCreator creator) {
getRegistry()[name] = creator;
}
static std::unique_ptr createShape(const std::string& name) {
auto it = getRegistry().find(name);
if (it != getRegistry().end()) {
return it->second();
}
return nullptr;
}
private:
static std::unordered_map& getRegistry() {
static std::unordered_map registry;
return registry;
}
};
// 注册具体类
int main() {
ShapeFactory::registerShape("circle", []() { return std::make_unique(); });
ShapeFactory::registerShape("rectangle", []() { return std::make_unique(); });
auto shape1 = ShapeFactory::createShape("circle");
auto shape2 = ShapeFactory::createShape("rectangle");
shape1->draw();
shape2->draw();
return 0;
}
这个示例展示了如何使用注册表模式和智能指针实现一个简单的形状工厂。你可以根据需要扩展这个示例,以支持更多的形状类型和更复杂的创建逻辑。