一、抽象工厂模式的核心概念
抽象工厂模式是一种创建型设计模式,其核心作用是提供一个接口,用于创建一系列相互关联或相互依赖的对象,而无需指定它们的具体类。简单来说,它就像一个"超级工厂",这个工厂不仅能生产单一产品,还能生产一整套配套的产品系列。
我们以日常家具使用场景为例:家庭装修时,我们通常会选择同一风格的家具,比如现代简约风格的沙发+茶几,或者古典实木风格的沙发+茶几。这里的"现代风格家具厂"和"古典风格家具厂"就相当于抽象工厂模式中的具体工厂,它们各自能生产一套配套的家具产品(沙发、茶几),而"家具工厂"则是抽象工厂接口,定义了生产沙发和茶几的统一规范。
二、抽象工厂模式的核心角色
-
抽象工厂(Abstract Factory):定义创建一系列相关产品的接口,包含多个创建产品的纯虚函数。对应例子中的"家具工厂",定义生产"沙发"和"茶几"的接口。
-
具体工厂(Concrete Factory):实现抽象工厂定义的接口,负责创建某一具体风格的产品系列。对应例子中的"现代风格家具厂"和"古典风格家具厂",分别生产现代风格的沙发+茶几和古典风格的沙发+茶几。
-
抽象产品(Abstract Product):定义某一类产品的接口,是具体产品的父类。对应例子中的"沙发"和"茶几",各自定义了家具的基础功能(如展示风格)。
-
具体产品(Concrete Product):实现抽象产品的接口,是具体工厂生产的实际对象。对应例子中的"现代沙发""古典沙发""现代茶几""古典茶几",各自实现了对应风格的具体功能。
三、C++代码示例:家具生产工厂
我们通过"不同风格家具生产"的场景来实现抽象工厂模式,需求为:创建现代风格和古典风格的家具工厂,每个工厂都能生产配套的沙发和茶几,并展示家具的风格。
3.1 代码实现
cpp
#include <iostream>
#include <string>
using namespace std;
// ---------------------- 抽象产品 ----------------------
// 抽象产品1:沙发
class Sofa {
public:
// 纯虚函数:展示沙发风格(抽象产品的核心接口)
virtual void showStyle() = 0;
// 虚析构函数:确保子类对象正确析构
virtual ~Sofa() {}
};
// 抽象产品2:茶几
class CoffeeTable {
public:
// 纯虚函数:展示茶几风格(抽象产品的核心接口)
virtual void showStyle() = 0;
// 虚析构函数:确保子类对象正确析构
virtual ~CoffeeTable() {}
};
// ---------------------- 具体产品 ----------------------
// 具体产品1.1:现代风格沙发
class ModernSofa : public Sofa {
public:
void showStyle() override {
cout << "这是现代风格沙发,设计简约,线条流畅" << endl;
}
};
// 具体产品1.2:古典风格沙发
class ClassicSofa : public Sofa {
public:
void showStyle() override {
cout << "这是古典风格沙发,雕刻精美,材质厚重" << endl;
}
};
// 具体产品2.1:现代风格茶几
class ModernCoffeeTable : public CoffeeTable {
public:
void showStyle() override {
cout << "这是现代风格茶几,玻璃台面,金属支架" << endl;
}
};
// 具体产品2.2:古典风格茶几
class ClassicCoffeeTable : public CoffeeTable {
public:
void showStyle() override {
cout << "这是古典风格茶几,实木材质,雕花装饰" << endl;
}
};
// ---------------------- 抽象工厂 ----------------------
// 抽象家具工厂:定义生产沙发和茶几的接口(产品系列)
class AbstractFurnitureFactory {
public:
// 纯虚函数:创建沙发
virtual Sofa* createSofa() = 0;
// 纯虚函数:创建茶几
virtual CoffeeTable* createCoffeeTable() = 0;
// 虚析构函数:确保子类工厂正确析构
virtual ~AbstractFurnitureFactory() {}
};
// ---------------------- 具体工厂 ----------------------
// 具体工厂1:现代风格家具厂(生产现代系列产品)
class ModernFurnitureFactory : public AbstractFurnitureFactory {
public:
Sofa* createSofa() override {
// 生产现代风格沙发
return new ModernSofa();
}
CoffeeTable* createCoffeeTable() override {
// 生产现代风格茶几(与沙发配套)
return new ModernCoffeeTable();
}
};
// 具体工厂2:古典风格家具厂(生产古典系列产品)
class ClassicFurnitureFactory : public AbstractFurnitureFactory {
public:
Sofa* createSofa() override {
// 生产古典风格沙发
return new ClassicSofa();
}
CoffeeTable* createCoffeeTable() override {
// 生产古典风格茶几(与沙发配套)
return new ClassicCoffeeTable();
}
};
// ---------------------- 客户端代码 ----------------------
// 客户端使用:传入具体工厂,获取配套产品并使用
void clientCode(AbstractFurnitureFactory* factory) {
// 从工厂获取沙发和茶几(无需关心具体类型,只依赖抽象接口)
Sofa* sofa = factory->createSofa();
CoffeeTable* coffeeTable = factory->createCoffeeTable();
// 使用产品(多态调用,展示对应风格)
cout << "=== 家具套装展示 ===" << endl;
sofa->showStyle();
coffeeTable->showStyle();
// 释放资源
delete sofa;
delete coffeeTable;
}
int main() {
// 场景1:购买现代风格家具套装
cout << "--- 购买现代风格家具 ---" << endl;
AbstractFurnitureFactory* modernFactory = new ModernFurnitureFactory();
clientCode(modernFactory);
delete modernFactory;
// 场景2:购买古典风格家具套装
cout << "\n--- 购买古典风格家具 ---" << endl;
AbstractFurnitureFactory* classicFactory = new ClassicFurnitureFactory();
clientCode(classicFactory);
delete classicFactory;
return 0;
}
3.2 代码说明
-
抽象产品层 :定义
Sofa和CoffeeTable两个抽象类,均包含纯虚函数showStyle(),明确了家具"展示风格"的核心功能。 -
具体产品层 :每个抽象产品对应两个具体实现(现代风格和古典风格),如
ModernSofa和ClassicSofa,分别实现了不同风格的showStyle()方法。 -
抽象工厂层 :
AbstractFurnitureFactory定义了创建沙发和茶几的两个纯虚函数,确保具体工厂必须生产这一套配套产品。 -
具体工厂层 :
ModernFurnitureFactory和ClassicFurnitureFactory分别实现了抽象工厂的接口,生产对应风格的配套家具,保证了产品系列的一致性。 -
客户端层 :
clientCode()函数仅依赖抽象工厂和抽象产品接口,无需知道具体产品的创建细节。当需要更换家具风格时,只需替换具体工厂对象(如从ModernFurnitureFactory换成ClassicFurnitureFactory),无需修改客户端核心逻辑。
四、抽象工厂模式的适用场景与优缺点
4.1 适用场景
-
需要创建一系列配套产品时,如例子中的"沙发+茶几"套装、电子设备的"手机+充电器"套装等。
-
希望隔离产品的具体实现,客户端仅依赖抽象接口,便于后续扩展新的产品系列(如新增"北欧风格家具厂")。
-
需要确保产品系列的一致性,避免出现"现代沙发+古典茶几"这种不配套的组合。
4.2 优点
-
保证产品系列的一致性:具体工厂只生产配套产品,避免不兼容的产品组合。
-
降低耦合度:客户端与具体产品解耦,仅通过抽象接口交互,符合"依赖倒置原则"。
-
便于扩展新的产品系列:新增风格(如北欧风格)时,只需新增具体产品类和具体工厂类,无需修改现有代码,符合"开闭原则"。
4.3 缺点
-
扩展新的产品种类成本高:若要新增产品(如在家具系列中新增"衣柜"),需修改抽象工厂接口及所有具体工厂的实现,违反"开闭原则"。
-
类数量膨胀:每增加一个产品系列或一个产品种类,都需要新增多个类(抽象产品、具体产品、具体工厂),导致系统类结构复杂。
五、总结
抽象工厂模式是解决"配套产品创建"问题的核心模式,通过抽象工厂定义产品系列的创建规范,具体工厂实现某一风格的产品生产,客户端依赖抽象接口实现解耦。在日常开发中,当遇到"一系列相互关联的产品需要统一创建"的场景(如UI组件库、设备驱动套件等),抽象工厂模式会是理想的选择。但需注意其"扩展产品种类成本高"的局限性,在设计时需合理规划产品系列的范围。