抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
抽象工厂模式提供了一种创建一系列相关或相互依赖对象的接口,而无需指定具体实现类。通过使用抽象工厂模式,可以将客户端与具体产品的创建过程解耦,使得客户端可以通过工厂接口来创建一族产品。
介绍
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决:主要解决接口选择的问题。
何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
如何解决:在一个产品族里面,定义多个产品。
关键代码:在一个工厂里聚合多个同类产品。
抽象工厂模式适合应用场景
如果代码需要与多个不同系列的相关产品交互, 但是由于无法提前获取相关信息, 或者出于对未来扩展性的考虑, 你不希望代码基于产品的具体类进行构建, 在这种情况下, 你可以使用抽象工厂。
抽象工厂为你提供了一个接口, 可用于创建每个系列产品的对象。 只要代码通过该接口创建对象, 那么你就不会生成与应用程序已生成的产品类型不一致的产品。
如果你有一个基于一组抽象方法的类, 且其主要功能因此变得不明确, 那么在这种情况下可以考虑使用抽象工厂模式。
在设计良好的程序中, 每个类仅负责一件事。 如果一个类与多种类型产品交互, 就可以考虑将工厂方法抽取到独立的工厂类或具备完整功能的抽象工厂类中。
抽象工厂模式优缺点
优点:
- 你可以确保同一工厂生成的产品相互匹配。
- 你可以避免客户端和具体产品代码的耦合。
- 单一职责原则。 你可以将产品生成代码抽取到同一位置, 使得代码易于维护。
- 开闭原则。 向应用程序中引入新产品变体时, 你无需修改客户端代码。
缺点:
- 由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂。
- 产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
示例代码如下:
#include <iostream>
// 抽象产品
class Button {
public:
virtual void paint() = 0;
};
class TextBox {
public:
virtual void paint() = 0;
};
// 具体产品
class WinButton : public Button {
public:
void paint() override {
std::cout << "Render a Windows Button" << std::endl;
}
};
class WinTextBox : public TextBox {
public:
void paint() override {
std::cout << "Render a Windows TextBox" << std::endl;
}
};
class MacButton : public Button {
public:
void paint() override {
std::cout << "Render a Mac Button" << std::endl;
}
};
class MacTextBox : public TextBox {
public:
void paint() override {
std::cout << "Render a Mac TextBox" << std::endl;
}
};
// 抽象工厂
class GUIFactory {
public:
virtual Button* createButton() = 0;
virtual TextBox* createTextBox() = 0;
};
// 具体工厂
class WinFactory : public GUIFactory {
public:
Button* createButton() override {
return new WinButton();
}
TextBox* createTextBox() override {
return new WinTextBox();
}
};
class MacFactory : public GUIFactory {
public:
Button* createButton() override {
return new MacButton();
}
TextBox* createTextBox() override {
return new MacTextBox();
}
};
// 客户端代码
int main() {
GUIFactory* winFactory = new WinFactory();
Button* winButton = winFactory->createButton();
TextBox* winTextBox = winFactory->createTextBox();
winButton->paint();
winTextBox->paint();
GUIFactory* macFactory = new MacFactory();
Button* macButton = macFactory->createButton();
TextBox* macTextBox = macFactory->createTextBox();
macButton->paint();
macTextBox->paint();
delete winButton;
delete winTextBox;
delete macButton;
delete macTextBox;
delete winFactory;
delete macFactory;
return 0;
}
输出:
Render a Windows Button
Render a Windows TextBox
Render a Mac Button
Render a Mac TextBox
通过上述代码可以看出,抽象工厂模式将产品的创建与使用分离,使得客户端代码只需关心产品的使用,而不需要关心产品的创建过程。同时,它也提高了代码的可扩展性和可维护性。