核心思想
工厂方法模式是一种创建型设计模式,它定义了一个用于创建对象的接口,但让子类决定实例化哪一个类。工厂方法模式将对象的实例化过程推迟到子类,从而使得子类可以根据需要决定创建哪种对象。
**Product:**定义产品的接口。
**ConcreteProduct:**实现Product接口,是具体的产品。
**Factory:**定义工厂方法,返回一个Product对象。
**ConcreteFactory:**实现工厂方法,返回具体的ConcreteProduct。
工厂方法模式的核心是将对象的创建与使用分离,使得系统更加灵活和可扩展。
使用场景
框架设计:如框架需要定义通用的创建逻辑,但将具体实现留给子类。
可扩展性需求:当系统需要支持多种产品类型,且未来可能新增产品时。
解耦创建逻辑:当对象的创建逻辑复杂,或需要依赖外部资源时。
测试与模拟:在测试中,可以使用工厂方法创建模拟对象。
插件化架构:如插件系统需要动态加载和创建对象。
解决的问题
紧耦合问题:
在传统设计中,客户端直接通过new关键字创建对象,导致客户端与具体类紧耦合。工厂方法模式通过引入工厂接口,解耦了客户端和具体类。
代码重复问题:
如果多个地方需要创建相同的对象,创建逻辑可能分散在各处,导致代码重复。工厂方法模式将创建逻辑集中管理。
扩展性问题:
新增产品类型时,需要修改客户端代码。工厂方法模式允许通过新增子类来扩展系统,而无需修改现有代码。
复杂创建逻辑:
如果对象的创建逻辑复杂(如依赖注入、配置加载等),直接嵌入在客户端代码中会导致代码难以维护。工厂方法模式将复杂逻辑封装在工厂类中。
优点
开闭原则:新增产品类型只需添加新的工厂子类,无需修改现有代码。
解耦:客户端只需依赖工厂接口,而不需要知道具体产品的实现。
复用性:创建逻辑可以在多个上下文中复用。
可测试性:可以通过工厂方法创建模拟对象,便于测试。
缺点
类数量增加:每个产品都需要一个对应的工厂子类,可能导致类的数量增多。
复杂性增加:对于简单对象的创建,使用工厂方法模式可能显得过于复杂。
客户端需要了解工厂:客户端需要知道有哪些工厂,并选择合适的工厂。
示例代码
下面是一个基于C++11的工厂方法模式的示例,展示了如何通过工厂类来创建不同类型的对象。
#include <iostream>
#include <memory>
// 抽象产品类
class Product {
public:
virtual void use() = 0;
virtual ~Product() = default;
};
// 具体产品类A
class ConcreteProductA : public Product {
public:
void use() override {
std::cout << "Using ConcreteProductA" << std::endl;
}
};
// 具体产品类B
class ConcreteProductB : public Product {
public:
void use() override {
std::cout << "Using ConcreteProductB" << std::endl;
}
};
// 抽象工厂类
class Factory {
public:
virtual std::unique_ptr<Product> createProduct() = 0;
virtual ~Factory() = default;
};
// 具体工厂类A
class ConcreteFactoryA : public Factory {
public:
std::unique_ptr<Product> createProduct() override {
return std::make_unique<ConcreteProductA>();
}
};
// 具体工厂类B
class ConcreteFactoryB : public Factory {
public:
std::unique_ptr<Product> createProduct() override {
return std::make_unique<ConcreteProductB>();
}
};
// 客户端代码
int main() {
std::unique_ptr<Factory> factoryA = std::make_unique<ConcreteFactoryA>();
std::unique_ptr<Product> productA = factoryA->createProduct();
productA->use();
std::unique_ptr<Factory> factoryB = std::make_unique<ConcreteFactoryB>();
std::unique_ptr<Product> productB = factoryB->createProduct();
productB->use();
return 0;
}
代码解析
抽象产品类 Product:定义了产品的接口,所有具体产品类都必须实现 use() 方法。
具体产品类 ConcreteProductA 和 ConcreteProductB:分别实现了 Product 接口,定义了各自的行为。
抽象工厂类 Factory:定义了工厂方法的接口,用于创建产品对象。
具体工厂类 ConcreteFactoryA 和 ConcreteFactoryB:分别实现了 Factory 接口,负责创建具体的产品对象。
客户端代码:通过工厂类创建产品对象,并调用其方法。