1.简介
抽象工厂模式是一种创建型设计模式,它提供了一个接口,用于创建一系列相关或依赖对象,而无需指定它们的具体类。这个模式通过组合多个工厂类,实现了对产品族的创建。
在C语言中,由于没有面向对象的特性(如类和继承),我们通过结构体和函数指针来模拟实现抽象工厂模式。
2.通俗讲解
想象你在不同的汽车制造厂订购汽车。每个工厂可以生产不同的汽车部件(比如发动机、轮胎),而这些部件都属于同一个品牌。你可能会去“品牌A”的工厂订购发动机和轮胎,也可能去“品牌B”的工厂订购相同的部件,但这些部件的具体实现细节不同。
抽象工厂模式就像一个工厂的集合,每个工厂可以生产属于自己品牌的一组产品,而你可以通过抽象工厂来获得这些工厂提供的产品。
3.实战
3.1.代码
#include <stdio.h>
/*
1. 定义产品接口
首先,我们定义抽象产品接口,包括Engine(发动机)和Tire(轮胎)。
*/
// 定义抽象产品接口 Engine
typedef struct Engine {
void (*start)(void);
} Engine;
// 定义抽象产品接口 Tire
typedef struct Tire {
void (*roll)(void);
} Tire;
/*
2. 实现具体产品
接下来,我们为两个品牌A和B分别实现具体的产品(发动机和轮胎)。
*/
// 品牌A的具体实现
void startEngineA() {
printf("Engine A is starting...\n");
}
void rollTireA() {
printf("Tire A is rolling...\n");
}
Engine* createEngineA() {
static Engine engineA = { startEngineA };
return &engineA;
}
Tire* createTireA() {
static Tire tireA = { rollTireA };
return &tireA;
}
// 品牌B的具体实现
void startEngineB() {
printf("Engine B is starting...\n");
}
void rollTireB() {
printf("Tire B is rolling...\n");
}
Engine* createEngineB() {
static Engine engineB = { startEngineB };
return &engineB;
}
Tire* createTireB() {
static Tire tireB = { rollTireB };
return &tireB;
}
/*
3. 定义抽象工厂接口
我们定义一个抽象工厂接口,它包含了创建产品的方法。
*/
// 抽象工厂接口
typedef struct CarFactory {
Engine* (*createEngine)(void);
Tire* (*createTire)(void);
} CarFactory;
/*
4. 实现具体工厂
我们为品牌A和品牌B分别实现具体的工厂,它们提供创建对应产品的功能。
*/
// 品牌A的工厂实现
CarFactory* createFactoryA() {
static CarFactory factoryA = { createEngineA, createTireA };
return &factoryA;
}
// 品牌B的工厂实现
CarFactory* createFactoryB() {
static CarFactory factoryB = { createEngineB, createTireB };
return &factoryB;
}
/*
5. 编写客户端代码
最后,我们编写客户端代码,通过选择不同的工厂来创建和使用产品。
*/
int main() {
// 选择品牌A的工厂
CarFactory* factoryA = createFactoryA();
Engine* engineA = factoryA->createEngine();
Tire* tireA = factoryA->createTire();
// 运行品牌A的产品
engineA->start();
tireA->roll();
// 选择品牌B的工厂
CarFactory* factoryB = createFactoryB();
Engine* engineB = factoryB->createEngine();
Tire* tireB = factoryB->createTire();
// 运行品牌B的产品
engineB->start();
tireB->roll();
return 0;
}
3.2.代码解析
- CarFactory 是抽象工厂接口,定义了创建 Engine 和 Tire 的方法。
- createFactoryA 和 createFactoryB 是两个具体的工厂函数,分别生成品牌A和品牌B的产品。
- 在 main 函数中,通过选择不同的工厂,我们得到了品牌A和品牌B的产品,并使用它们。
3.3.代码运行
Engine A is starting...
Tire A is rolling...
Engine B is starting...
Tire B is rolling...
3.4.结果分析
通过这个例子,我们可以看到抽象工厂模式的威力。客户端代码只需要知道自己要使用哪个品牌的工厂,而不需要关心具体的产品实现细节。这使得代码更具扩展性和可维护性。当我们需要新增品牌时,只需添加新的具体工厂和产品,而无需修改客户端代码。
4.总结
核心思想:
- 抽象工厂接口定义了创建一组相关对象的方法。每个具体工厂实现了这些方法来生成特定的产品。
- 具体工厂类负责实现抽象工厂接口,创建一组相关的具体产品(如发动机和轮胎)。
- 客户端代码通过使用具体工厂,创建所需的产品对象,但无需关心具体实现细节。
优点:
- 产品族的一致性:抽象工厂模式确保同一工厂生成的产品可以协同工作,避免了不同产品之间的兼容性问题。
- 解耦性:客户端与具体产品的实现细节解耦,便于扩展和维护。新增产品族时,只需添加相应的具体工厂,不必修改客户端代码。
缺点
- 扩展困难:如果需要增加新的产品类型,必须修改抽象工厂接口及所有具体工厂的实现,这对扩展有一定的挑战。