工厂模式
1. 简单工厂模式(Simple Factory)
核心思想
- 定义一个工厂类,根据输入参数创建不同的具体对象。
- 客户端不直接调用具体类的构造函数,而是通过工厂类获取对象。
示例代码
cpp
#include <iostream>
#include <memory>
// 抽象产品类
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() = default;
};
// 具体产品类:圆形
class Circle : public Shape {
public:
void draw() override {
std::cout << "Drawing a Circle" << std::endl;
}
};
// 具体产品类:矩形
class Rectangle : public Shape {
public:
void draw() override {
std::cout << "Drawing a Rectangle" << std::endl;
}
};
// 简单工厂类
class ShapeFactory {
public:
enum class Type { Circle, Rectangle };
// 创建对象的方法
static std::unique_ptr<Shape> createShape(Type type) {
switch (type) {
case Type::Circle:
return std::make_unique<Circle>();
case Type::Rectangle:
return std::make_unique<Rectangle>();
default:
throw std::invalid_argument("Invalid shape type");
}
}
};
// 客户端使用
int main() {
auto circle = ShapeFactory::createShape(ShapeFactory::Type::Circle);
circle->draw(); // Output: Drawing a Circle
auto rect = ShapeFactory::createShape(ShapeFactory::Type::Rectangle);
rect->draw(); // Output: Drawing a Rectangle
return 0;
}
特点
- 优点:代码简单,集中管理对象的创建逻辑。
- 缺点:违反开闭原则(新增类型需修改工厂类)。
2. 工厂方法模式(Factory Method)
核心思想
- 定义一个创建对象的抽象接口,由子类决定具体实例化的类。
- 每个具体产品对应一个具体工厂类。
示例代码
cpp
#include <iostream>
#include <memory>
// 抽象产品类
class Button {
public:
virtual void render() = 0;
virtual ~Button() = default;
};
// 具体产品类:Windows 按钮
class WindowsButton : public Button {
public:
void render() override {
std::cout << "Rendering a Windows-style button" << std::endl;
}
};
// 具体产品类:MacOS 按钮
class MacOSButton : public Button {
public:
void render() override {
std::cout << "Rendering a MacOS-style button" << std::endl;
}
};
// 抽象工厂类
class ButtonFactory {
public:
virtual std::unique_ptr<Button> createButton() = 0;
virtual ~ButtonFactory() = default;
};
// 具体工厂类:Windows 按钮工厂
class WindowsButtonFactory : public ButtonFactory {
public:
std::unique_ptr<Button> createButton() override {
return std::make_unique<WindowsButton>();
}
};
// 具体工厂类:MacOS 按钮工厂
class MacOSButtonFactory : public ButtonFactory {
public:
std::unique_ptr<Button> createButton() override {
return std::make_unique<MacOSButton>();
}
};
// 客户端使用
void renderUI(ButtonFactory& factory) {
auto button = factory.createButton();
button->render();
}
int main() {
WindowsButtonFactory winFactory;
renderUI(winFactory); // Output: Rendering a Windows-style button
MacOSButtonFactory macFactory;
renderUI(macFactory); // Output: Rendering a MacOS-style button
return 0;
}
特点
- 优点:符合开闭原则,扩展新类型只需添加新工厂类。
- 缺点:类数量增加,系统复杂度提升。
3. 抽象工厂模式(Abstract Factory)
核心思想
- 提供一个接口,用于创建一组相关或依赖的对象家族。
- 适合需要创建多个协同工作的对象的场景(如 GUI 组件库)。
示例代码
cpp
#include <iostream>
#include <memory>
// 抽象产品类:按钮
class Button {
public:
virtual void render() = 0;
virtual ~Button() = default;
};
// 抽象产品类:文本框
class TextBox {
public:
virtual void input() = 0;
virtual ~TextBox() = default;
};
// Windows 系列产品
class WindowsButton : public Button {
public:
void render() override {
std::cout << "Windows Button" << std::endl;
}
};
class WindowsTextBox : public TextBox {
public:
void input() override {
std::cout << "Windows TextBox" << std::endl;
}
};
// MacOS 系列产品
class MacOSButton : public Button {
public:
void render() override {
std::cout << "MacOS Button" << std::endl;
}
};
class MacOSTextBox : public TextBox {
public:
void input() override {
std::cout << "MacOS TextBox" << std::endl;
}
};
// 抽象工厂接口
class GUIFactory {
public:
virtual std::unique_ptr<Button> createButton() = 0;
virtual std::unique_ptr<TextBox> createTextBox() = 0;
virtual ~GUIFactory() = default;
};
// 具体工厂:Windows 工厂
class WindowsFactory : public GUIFactory {
public:
std::unique_ptr<Button> createButton() override {
return std::make_unique<WindowsButton>();
}
std::unique_ptr<TextBox> createTextBox() override {
return std::make_unique<WindowsTextBox>();
}
};
// 具体工厂:MacOS 工厂
class MacOSFactory : public GUIFactory {
public:
std::unique_ptr<Button> createButton() override {
return std::make_unique<MacOSButton>();
}
std::unique_ptr<TextBox> createTextBox() override {
return std::make_unique<MacOSTextBox>();
}
};
// 客户端使用
void createUI(GUIFactory& factory) {
auto button = factory.createButton();
auto textBox = factory.createTextBox();
button->render();
textBox->input();
}
int main() {
WindowsFactory winFactory;
createUI(winFactory);
// Output:
// Windows Button
// Windows TextBox
MacOSFactory macFactory;
createUI(macFactory);
// Output:
// MacOS Button
// MacOS TextBox
return 0;
}
特点
- 优点:保证产品家族的兼容性(如统一风格)。
- 缺点:扩展新产品家族需要修改所有工厂接口。
工厂模式的核心对比
模式 | 适用场景 | 扩展性 | 复杂度 |
---|---|---|---|
简单工厂 | 对象类型少且固定 | 违反开闭原则 | 低 |
工厂方法 | 单一产品,需灵活扩展具体类型 | 新增产品类型只需添加新工厂 | 中 |
抽象工厂 | 需要创建一组相关的对象(产品家族) | 新增产品家族需修改接口 | 高 |
工厂模式的典型应用场景
- 跨平台 UI 开发:为不同操作系统创建风格一致的组件。
- 游戏开发:动态生成不同类别的敌人或道具。
- 数据库访问:根据配置创建 MySQL/Oracle 连接对象。
- 插件系统:加载第三方模块时动态创建对象。
最佳实践
-
优先使用工厂方法模式 :
在需要灵活扩展时,避免简单工厂的硬编码逻辑。
-
结合智能指针管理对象 :
使用
std::unique_ptr
或std::shared_ptr
自动释放资源。c++std::unique_ptr<Button> button = factory.createButton();
-
避免过度设计 :
如果对象创建逻辑简单,直接使用构造函数可能更高效。
总结
工厂模式通过封装对象的创建过程,实现以下目标:
- 解耦:客户端代码与具体类解耦。
- 可维护性:集中管理创建逻辑,便于修改和扩展。
- 灵活性:支持动态切换产品类型或家族。