1.简介
抽象工厂模式是一种创建型设计模式,它提供了一个接口用于创建一系列相关或相互依赖的对象,而无需指定它们具体的类。在抽象工厂模式中,我们创建对象集合,这些对象通常属于同一“系列”或者有着共同的主题,而不需要知道具体是哪些类生成了这些对象。
抽象工厂模式的应用场景
抽象工厂模式适用于以下情况:
- 当系统需要独立于它的产品创建、组合和表示时。
- 当系统要由多个产品系列中的一个来配置时。
- 当添加新的产品系列时,整个系统不会受到影响。
2.通俗讲解
假设我们要创建一个游戏系统,该系统中有不同的角色类型(如战士、法师),并且每个角色都有不同的武器装备(如剑、杖)。我们需要根据不同的游戏环境(如奇幻世界、科幻世界)来创建不同的角色及其装备。
3.实战
3.1.代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义武器结构体
typedef struct Weapon {
char *name;
} Weapon;
// 定义角色结构体
typedef struct Character {
char *name;
Weapon *weapon;
} Character;
// 定义抽象工厂接口
typedef struct Factory {
Character *(*createCharacter)(char *);
Weapon *(*createWeapon)(char *);
} Factory;
// 奇幻世界工厂的实现
Character *fantasyCreateCharacter(char *name) {
Character *character = malloc(sizeof(Character));
character->name = strdup(name);
character->weapon = fantasyCreateWeapon("Sword");
return character;
}
Weapon *fantasyCreateWeapon(char *name) {
Weapon *weapon = malloc(sizeof(Weapon));
weapon->name = strdup(name);
return weapon;
}
Factory *fantasyFactory() {
Factory *factory = malloc(sizeof(Factory));
factory->createCharacter = fantasyCreateCharacter;
factory->createWeapon = fantasyCreateWeapon;
return factory;
}
// 科幻世界工厂的实现
Character *sciFiCreateCharacter(char *name) {
Character *character = malloc(sizeof(Character));
character->name = strdup(name);
character->weapon = sciFiCreateWeapon("Laser Gun");
return character;
}
Weapon *sciFiCreateWeapon(char *name) {
Weapon *weapon = malloc(sizeof(Weapon));
weapon->name = strdup(name);
return weapon;
}
Factory *sciFiFactory() {
Factory *factory = malloc(sizeof(Factory));
factory->createCharacter = sciFiCreateCharacter;
factory->createWeapon = sciFiCreateWeapon;
return factory;
}
// 主程序
int main() {
Factory *fantasy = fantasyFactory();
Factory *sciFi = sciFiFactory();
Character *fantasyCharacter = fantasy->createCharacter("Aragon");
Character *sciFiCharacter = sciFi->createCharacter("Space Marine");
printf("Fantasy Character: %s with %s\n", fantasyCharacter->name, fantasyCharacter->weapon->name);
printf("SciFi Character: %s with %s\n", sciFiCharacter->name, sciFiCharacter->weapon->name);
// 清理资源
free(fantasyCharacter->weapon->name);
free(fantasyCharacter->weapon);
free(fantasyCharacter->name);
free(fantasyCharacter);
free(sciFiCharacter->weapon->name);
free(sciFiCharacter->weapon);
free(sciFiCharacter->name);
free(sciFiCharacter);
free(fantasy);
free(sciFi);
return 0;
}
3.2.代码解析
- 抽象工厂 (
Factory
) 是一个结构体,其中包含了两个函数指针createCharacter
和createWeapon
,分别用来创建角色和武器。 - 具体工厂 (
fantasyFactory
和sciFiFactory
) 创建了各自的工厂实例,并指定了创建角色和武器的具体实现。 - 角色和武器 (
Character
和Weapon
) 结构体定义了每个实体的基本属性。 - 在
main
函数中,我们创建了两个工厂实例,并使用它们来创建角色和武器。
这种设计允许我们轻松地添加新的工厂类型(例如,未来还可以添加“古代世界”或“现代世界”的工厂),只需要遵循相同的接口即可。这使得代码具有良好的扩展性和可维护性。
3.3.代码运行
Fantasy Character: Aragon with Sword
SciFi Character: Space Marine with Laser Gun
4.总结
对抽象工厂模式的一个简单总结:
- 抽象工厂:提供一个接口,用于创建一组相关或相互依赖的对象,而不需要指定这些对象所属的具体类。
- 具体工厂:实现抽象工厂接口,负责创建具体的产品族对象。
- 产品接口:定义了每一种产品的接口,即定义了产品对象的行为。
- 具体产品:实现了产品接口,由具体工厂生产。
组成部分
- AbstractFactory (抽象工厂):声明一个或多个创建产品的接口方法。
- ConcreteFactory (具体工厂):实现抽象工厂中的方法,用于创建并返回具体产品对象。
- Product (产品接口):定义了所有同类产品的公共接口。
- ConcreteProduct (具体产品):实现了产品接口,是实际创建的对象。
优点
- 提供了一组相关或相互依赖的对象的接口,无需指定它们的具体类。
- 可以在代码中注入不同的具体工厂来改变整个产品系列。
- 更容易管理产品之间的依赖关系。
缺点
- 当系统中加入新产品时,需要修改抽象工厂和具体工厂的代码。
- 如果产品族中的某些产品没有在所有工厂中实现,则需要考虑如何处理这些未实现的产品。
使用场景
- 当你需要创建一组相关或相互依赖的对象,但具体类不确定时。
- 当你希望在代码中通过配置文件或参数来决定使用哪一组产品时。
示例
在之前的示例中,我们定义了一个抽象工厂 Factory
用于创建 Character
和 Weapon
。然后我们实现了两个具体工厂 fantasyFactory
和 sciFiFactory
来创建奇幻世界和科幻世界的角色与武器。
通过这种方式,我们可以很容易地扩展到其他类型的世界,比如古代世界或未来世界,只需要增加相应的具体工厂实现即可。