抽象工厂模式是一种创建型设计模式,其核心思想是提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。它允许客户端通过抽象接口创建一组产品,而不必关心具体实现类。
抽象工厂(Abstract Factory):
createProductA()
、createProductB()
)。具体工厂(Concrete Factory):
抽象产品(Abstract Product):
具体产品(Concrete Product):
场景:跨平台UI组件工厂,支持创建Windows和macOS的按钮、文本框等组件。
// 抽象按钮
class Button {
public:
virtual void paint() = 0;
virtual ~Button() = default;
};
// 抽象文本框
class TextBox {
public:
virtual void render() = 0;
virtual ~TextBox() = default;
};
// Windows按钮
class WindowsButton : public Button {
public:
void paint() override {
std::cout << "Windows风格按钮" << std::endl;
}
};
// macOS按钮
class MacOSButton : public Button {
public:
void paint() override {
std::cout << "macOS风格按钮" << std::endl;
}
};
// Windows文本框
class WindowsTextBox : public TextBox {
public:
void render() override {
std::cout << "Windows风格文本框" << std::endl;
}
};
// macOS文本框
class MacOSTextBox : public TextBox {
public:
void render() override {
std::cout << "macOS风格文本框" << std::endl;
}
};
// 抽象工厂:创建UI组件
class UIComponentFactory {
public:
virtual Button* createButton() = 0;
virtual TextBox* createTextBox() = 0;
virtual ~UIComponentFactory() = default;
};
// Windows工厂
class WindowsFactory : public UIComponentFactory {
public:
Button* createButton() override {
return new WindowsButton();
}
TextBox* createTextBox() override {
return new WindowsTextBox();
}
};
// macOS工厂
class MacOSFactory : public UIComponentFactory {
public:
Button* createButton() override {
return new MacOSButton();
}
TextBox* createTextBox() override {
return new MacOSTextBox();
}
};
// 客户端:使用抽象工厂创建UI组件
void createUI(UIComponentFactory* factory) {
Button* button = factory->createButton();
TextBox* textBox = factory->createTextBox();
button->paint();
textBox->render();
delete button;
delete textBox;
}
int main() {
// 根据运行平台选择工厂
UIComponentFactory* factory;
#ifdef _WIN32
factory = new WindowsFactory();
#else
factory = new MacOSFactory();
#endif
createUI(factory);
delete factory;
return 0;
}
维度 | 简单工厂(Simple Factory) | 工厂方法(Factory Method) | 抽象工厂(Abstract Factory) |
---|---|---|---|
核心思想 | 通过一个工厂类创建所有产品 | 通过子类决定创建哪个具体产品 | 创建一组相关产品,无需指定具体类 |
工厂结构 | 单个工厂类 | 抽象工厂类 + 多个具体工厂子类 | 抽象工厂接口 + 多个具体工厂实现 |
产品类型 | 单一产品等级结构 | 单一产品等级结构 | 多个产品等级结构(产品族) |
扩展性 | 添加新产品需修改工厂类(违反开闭原则) | 添加新产品只需新增具体工厂子类 | 添加新产品族需新增具体工厂,修改抽象工厂接口 |
适用场景 | 产品种类少且稳定 | 产品创建逻辑多变 | 系统需独立于产品创建、组合和表示 |
优势:
适用场景:
扩展困难:
复杂度高:
抽象工厂模式的核心价值在于通过抽象接口封装一组产品的创建逻辑,使系统在产品族级别实现松耦合。它与其他工厂模式的区别在于:
在实际开发中,抽象工厂广泛应用于框架设计(如Spring的BeanFactory)、游戏开发(如不同风格的角色装备工厂)和企业系统(如多数据库支持)。
简单工厂模式通过switch-case
或if-else
判断创建具体产品:
// 简单工厂(存在问题)
class ShapeFactory {
public:
static Shape* createShape(const std::string& type) {
if (type == "circle") {
return new Circle();
} else if (type == "rectangle") {
return new Rectangle();
} else if (type == "triangle") {
return new Triangle();
}
return nullptr; // 未匹配类型
}
};
问题:
switch-case
。switch-case
会变得冗长且难以维护。依赖注入的核心思想是将对象的创建权交给外部,而非在类内部直接实例化。
// 抽象产品
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() = default;
};
// 具体产品
class Circle : public Shape {
public:
void draw() override { std::cout << "Circle" << std::endl; }
};
class Rectangle : public Shape {
public:
void draw() override { std::cout << "Rectangle" << std::endl; }
};
// 依赖注入:通过构造函数传入依赖
class ShapeRenderer {
private:
Shape* shape; // 依赖抽象,而非具体类
public:
explicit ShapeRenderer(Shape* s) : shape(s) {} // 构造函数注入
void render() { shape->draw(); }
};
// 客户端代码(负责创建对象)
int main() {
Shape* circle = new Circle();
ShapeRenderer renderer(circle); // 注入依赖
renderer.render(); // 输出:Circle
delete circle;
return 0;
}
优势:
switch-case
。将产品类型配置到文件中,运行时读取:
// 配置文件 config.json
{
"shapeType": "circle"
}
// 工厂类(简化版)
class ShapeFactory {
public:
static Shape* createShape(const std::string& configFile) {
std::string type = readTypeFromConfig(configFile); // 从配置读取类型
if (type == "circle") return new Circle();
if (type == "rectangle") return new Rectangle();
return nullptr;
}
};
优势:
反射允许程序在运行时获取类型信息并动态创建对象,避免硬编码switch-case
。
C++标准库无内置反射,但可通过函数注册表模拟:
#include
#include
// 产品注册表(反射核心)
class ShapeRegistry {
private:
using Creator = std::function<Shape*()>;
static std::unordered_map<std::string, Creator> registry;
public:
// 注册产品创建函数
static void registerShape(const std::string& type, Creator creator) {
registry[type] = creator;
}
// 通过类型名创建产品
static Shape* createShape(const std::string& type) {
auto it = registry.find(type);
if (it != registry.end()) {
return it->second(); // 调用注册的创建函数
}
return nullptr;
}
};
// 注册表实例
std::unordered_map<std::string, ShapeRegistry::Creator> ShapeRegistry::registry;
// 注册产品(静态初始化)
struct CircleRegistrar {
CircleRegistrar() {
ShapeRegistry::registerShape("circle", []() { return new Circle(); });
}
} circleRegistrar; // 全局变量触发注册
struct RectangleRegistrar {
RectangleRegistrar() {
ShapeRegistry::registerShape("rectangle", []() { return new Rectangle(); });
}
} rectangleRegistrar;
// 客户端使用
int main() {
Shape* circle = ShapeRegistry::createShape("circle"); // 动态创建
if (circle) {
circle->draw(); // 输出:Circle
delete circle;
}
return 0;
}
优势:
Java提供内置反射API:
// 工厂类
public class ShapeFactory {
public static Shape createShape(String className) {
try {
// 通过类名获取Class对象
Class<?> shapeClass = Class.forName(className);
// 创建实例
return (Shape) shapeClass.getDeclaredConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
// 客户端使用
public static void main(String[] args) {
// 通过全限定类名动态创建对象
Shape circle = ShapeFactory.createShape("com.example.Circle");
if (circle != null) {
circle.draw();
}
}
优势:
switch-case
,通过字符串类名动态创建对象。在大型框架(如Spring)中,依赖注入与反射常结合使用:
// Spring风格的依赖注入与反射结合
public class ApplicationContext {
private Map<String, BeanDefinition> beanDefinitions;
private Map<String, Object> singletonBeans;
// 从配置文件加载Bean定义
public void loadBeans(String configFile) {
// 解析配置文件,注册Bean定义
beanDefinitions = parseConfig(configFile);
}
// 获取Bean(通过反射创建)
public Object getBean(String beanName) {
if (singletonBeans.containsKey(beanName)) {
return singletonBeans.get(beanName);
}
BeanDefinition definition = beanDefinitions.get(beanName);
if (definition == null) {
throw new IllegalArgumentException("Bean not found: " + beanName);
}
// 通过反射创建实例
Class<?> clazz = Class.forName(definition.getClassName());
Object bean = clazz.getDeclaredConstructor().newInstance();
// 注入依赖(递归处理)
injectDependencies(bean, definition);
// 缓存单例
if (definition.isSingleton()) {
singletonBeans.put(beanName, bean);
}
return bean;
}
}
模式 | 解决思路 | 优点 | 缺点 |
---|---|---|---|
简单工厂 | 使用switch-case 判断创建逻辑 |
实现简单 | 违反开闭原则,扩展性差 |
依赖注入 | 将对象创建权交给客户端 | 松耦合,符合开闭原则 | 需要外部管理对象关系 |
反射 | 运行时动态创建对象 | 彻底消除switch-case ,高度灵活 |
性能开销,类型安全风险 |
依赖注入和反射通过以下方式解决简单工厂的switch-case
问题:
在实际应用中:
这些技术共同提升了代码的可维护性和可扩展性,是现代软件开发的核心模式。
反射允许程序在运行时动态创建对象,而配置文件则提供了一种外部化、可动态修改的参数存储方式。两者结合可实现:
可维护性:
灵活性:
安全性:
多环境适配:
nlohmann/json
)。yaml-cpp
)。示例JSON配置:
{
"database": {
"type": "MySQL",
"host": "localhost",
"port": 3306
},
"logger": {
"type": "FileLogger",
"level": "INFO",
"output": "app.log"
}
}
#include
#include
#include
#include
#include "nlohmann/json.hpp" // JSON解析库
using json = nlohmann::json;
// 基类接口
class Database {
public:
virtual void connect() = 0;
virtual ~Database() = default;
};
// 具体实现
class MySQL : public Database {
public:
void connect() override { /* 连接MySQL */ }
};
class PostgreSQL : public Database {
public:
void connect() override { /* 连接PostgreSQL */ }
};
// 反射注册表
class DatabaseRegistry {
private:
using Creator = std::function<std::unique_ptr<Database>(const json& config)>;
static std::unordered_map<std::string, Creator> registry;
public:
// 注册类型
static void registerType(const std::string& type, Creator creator) {
registry[type] = creator;
}
// 通过配置创建对象
static std::unique_ptr<Database> create(const json& config) {
std::string type = config["type"].get<std::string>();
auto it = registry.find(type);
if (it != registry.end()) {
return it->second(config); // 传递配置到创建函数
}
return nullptr;
}
};
// 初始化注册表
std::unordered_map<std::string, DatabaseRegistry::Creator> DatabaseRegistry::registry;
// 自动注册宏
#define REGISTER_DATABASE(type) \
struct type##Registrar { \
type##Registrar() { \
DatabaseRegistry::registerType(#type, [](const json& config) { \
auto db = std::make_unique<type>(); \
// 从config初始化db... \
return db; \
}); \
} \
}; \
static type##Registrar type##RegistrarInstance;
// 注册具体类型
REGISTER_DATABASE(MySQL)
REGISTER_DATABASE(PostgreSQL)
// 加载配置文件
json loadConfig(const std::string& path) {
std::ifstream file(path);
if (!file.is_open()) {
throw std::runtime_error("Failed to open config file");
}
return json::parse(file);
}
// 客户端代码
int main() {
try {
// 加载配置
json config = loadConfig("config.json");
// 通过反射创建对象
auto db = DatabaseRegistry::create(config["database"]);
if (db) {
db->connect(); // 连接数据库
}
// 创建日志记录器
auto logger = LoggerRegistry::create(config["logger"]);
if (logger) {
logger->log("System started");
}
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
return 0;
}
结合反射与动态库(DLL/so),实现插件化架构:
// 插件接口
class Plugin {
public:
virtual std::string getName() const = 0;
virtual void execute() = 0;
virtual ~Plugin() = default;
};
// 插件管理器
class PluginManager {
private:
std::vector<std::pair<void*, std::unique_ptr<Plugin>>> plugins;
public:
// 加载插件
void loadPlugin(const std::string& path, const json& config) {
void* handle = dlopen(path.c_str(), RTLD_LAZY); // Linux动态库加载
if (!handle) {
throw std::runtime_error("Failed to load plugin: " + std::string(dlerror()));
}
// 获取创建函数指针
using CreateFunc = Plugin*(*)(const json&);
CreateFunc create = reinterpret_cast<CreateFunc>(dlsym(handle, "createPlugin"));
if (!create) {
dlclose(handle);
throw std::runtime_error("Plugin does not implement createPlugin");
}
// 创建插件实例
plugins.emplace_back(handle, std::unique_ptr<Plugin>(create(config)));
}
// 卸载所有插件
~PluginManager() {
for (auto& pair : plugins) {
dlclose(pair.first);
}
}
};
性能开销:
类型安全:
内存管理:
错误处理:
反射与配置文件结合的核心价值在于将对象创建逻辑外部化、动态化,使系统更灵活、可扩展。在C++中实现时:
这种模式广泛应用于游戏引擎(如Unity的组件系统)、企业框架(如Spring的Bean配置)和大型应用(如Chrome的插件架构)。