1. 工厂方法模式(Factory Method Pattern)
将对象的创建延迟到子类中实现,每个具体产品类都有一个对应的工厂类负责创建,从而使得系统更加灵活。客户端可以通过调用工厂方法来创建所需的产品,而不必关心具体的实现细节。这种模式符合开放-封闭原则,对扩展开放、对修改关闭。
不同于 简单工厂模式 定义一个工厂方法来创建产品,工厂方法模式 的 每个产品都有一个对应的工厂类来创建。这样每个产品类和工厂类相互独立,可以独立进行扩展,符合开放-封闭原则。例如,在一个图形绘制软件中,可以使用 工厂方法模式 来创建不同类型的图形对象,如圆形、矩形、三角形等,每个图形都有一个对应的工厂类来创建。
假设我们要设计一个电子产品工厂来生产不同类型的产品,如手机、电视、电脑等。如果使用 简单工厂模式,我们需要一个工厂类来创建所有不同类型的电子产品,客户端代码需要指定电子产品类型,工厂类根据类型来创建相应的产品对象。但是,随着产品类型的增加,工厂类的代码会越来越复杂,难以维护和扩展。
相反,如果使用 工厂方法模式,每个产品类型都有一个对应的工厂类来创建,工厂方法 可以独立进行扩展,每个工厂类只需要关心自己负责的产品类型,代码更加清晰和易于维护。例如,手机工厂类负责创建手机产品对象,电视工厂类负责创建电视产品对象,电脑工厂类负责创建电脑产品对象等。客户端代码只需要知道所需的产品类型,选择对应的工厂类即可,不需要知道具体的创建细节。
2. 结构
2.1 角色
工厂方法模式是在简单工厂模式上的改进,主要包含如下几个角色及组件
- 抽象工厂(Creator):整个工厂模式的核心角色,它与应用无关,主要在创建模式中规范和产品对应的工厂对象的标准化定义。
- 具体工厂(Concrete Creator):实现了抽象工厂的具体工厂类,该类型是和应用直接交互的具体实现类,在应用程序中调用,用于创建产品对象。
- 抽象产品(Product):工厂方法模式创建的所有类型的超级父类,该类型和具体业务有关,用于规范工厂方法模式中创建的方法对象具备的公共特征行为。
- 具体产品(Concrete Product):该类型实现了抽象产品 父类,是工厂方法模式中具体创建的实例对象。
2.2 类图
3.优缺点
优点:
- 遵循开闭原则:工厂方法模式允许在不修改原有代码的情况下增加新的产品,这符合软件工程中的开闭原则,即对扩展开放,对修改关闭。当需要添加新产品时,只需要添加具体的产品类和对应的工厂类,而不需要修改已有的抽象工厂和客户端代码。
- 高扩展性:由于所有的具体工厂类都继承自同一个抽象父类,这使得系统在加入新产品时具有良好的扩展性。这种模式鼓励使用多态性,允许工厂自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。
- 隐藏了创建对象的复杂性:用户或客户端不需要关心创建对象的细节,甚至不需要知道具体产品类的类名,只需要关心所需产品对应的工厂即可。这有助于减少客户端与具体产品类之间的耦合度
缺点:
- 增加了类的数量:当有成千上万个类型的产品时,就需要有成千上万个工厂类来生产这些产品。这会增加系统的复杂度,需要编译和运行的类数量增加,可能会给系统带来额外的开销。
- 增加了系统的复杂度:在添加新产品时,需要编写新的具体产品类,并且还要提供与之对应的具体工厂类。这会导致系统中类的个数成对增加,从而增加了系统的复杂度。
4.示例
#include <iostream>
#include <string>
// 产品接口
class Animal {
public:
virtual void makeSound() = 0; // 纯虚函数
virtual ~Animal() {} // 虚析构函数
};
// 具体产品
class Dog : public Animal {
public:
void makeSound() override {
std::cout << "Woof!" << std::endl;
}
};
class Cat : public Animal {
public:
void makeSound() override {
std::cout << "Meow!" << std::endl;
}
};
// 工厂接口
class AnimalFactory {
public:
virtual Animal* createAnimal() = 0; // 纯虚函数,工厂方法
virtual ~AnimalFactory() {} // 虚析构函数
};
// 具体工厂
class DogFactory : public AnimalFactory {
public:
Animal* createAnimal() override {
return new Dog();
}
};
class CatFactory : public AnimalFactory {
public:
Animal* createAnimal() override {
return new Cat();
}
};
// 客户端代码,使用工厂方法模式
int main() {
AnimalFactory* factory;
// 根据用户输入或条件选择具体的工厂
std::string type;
std::cout << "Enter the type of animal factory ('dog' or 'cat'): ";
std::cin >> type;
if (type == "dog") {
factory = new DogFactory();
} else if (type == "cat") {
factory = new CatFactory();
} else {
std::cout << "Invalid factory type." << std::endl;
return 1;
}
// 使用工厂创建对象
Animal* animal = factory->createAnimal();
animal->makeSound();
delete animal; // 使用完对象后,记得释放内存
delete factory; // 释放工厂对象
return 0;
}
Animal
是一个产品接口,声明了所有动物必须实现的makeSound
方法。Dog
和Cat
是具体产品,它们继承自Animal
并实现了makeSound
方法。AnimalFactory
是工厂接口,声明了createAnimal
方法用于创建动物对象。DogFactory
和CatFactory
是具体工厂,它们继承自AnimalFactory
并实现了createAnimal
方法,分别返回Dog
和Cat
的实例。- 在
main
函数中,我们根据用户输入来创建相应的工厂对象,然后使用该工厂对象创建动物对象。
工厂方法模式允许系统在不修改客户端代码的情况下引入新的产品,提高了系统的扩展性和可维护性。