设计模式专题之C语言-抽象工厂模式

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.代码解析

  1. 抽象工厂 (Factory) 是一个结构体,其中包含了两个函数指针 createCharactercreateWeapon,分别用来创建角色和武器。
  2. 具体工厂 (fantasyFactorysciFiFactory) 创建了各自的工厂实例,并指定了创建角色和武器的具体实现。
  3. 角色和武器 (CharacterWeapon) 结构体定义了每个实体的基本属性。
  4. main 函数中,我们创建了两个工厂实例,并使用它们来创建角色和武器。

这种设计允许我们轻松地添加新的工厂类型(例如,未来还可以添加“古代世界”或“现代世界”的工厂),只需要遵循相同的接口即可。这使得代码具有良好的扩展性和可维护性。

3.3.代码运行

Fantasy Character: Aragon with Sword
SciFi Character: Space Marine with Laser Gun

4.总结

对抽象工厂模式的一个简单总结:

  • 抽象工厂:提供一个接口,用于创建一组相关或相互依赖的对象,而不需要指定这些对象所属的具体类。
  • 具体工厂:实现抽象工厂接口,负责创建具体的产品族对象。
  • 产品接口:定义了每一种产品的接口,即定义了产品对象的行为。
  • 具体产品:实现了产品接口,由具体工厂生产。

组成部分

  1. AbstractFactory (抽象工厂):声明一个或多个创建产品的接口方法。
  2. ConcreteFactory (具体工厂):实现抽象工厂中的方法,用于创建并返回具体产品对象。
  3. Product (产品接口):定义了所有同类产品的公共接口。
  4. ConcreteProduct (具体产品):实现了产品接口,是实际创建的对象。

优点

  • 提供了一组相关或相互依赖的对象的接口,无需指定它们的具体类。
  • 可以在代码中注入不同的具体工厂来改变整个产品系列。
  • 更容易管理产品之间的依赖关系。

缺点

  • 当系统中加入新产品时,需要修改抽象工厂和具体工厂的代码。
  • 如果产品族中的某些产品没有在所有工厂中实现,则需要考虑如何处理这些未实现的产品。

使用场景

  • 当你需要创建一组相关或相互依赖的对象,但具体类不确定时。
  • 当你希望在代码中通过配置文件或参数来决定使用哪一组产品时。

示例
在之前的示例中,我们定义了一个抽象工厂 Factory 用于创建 CharacterWeapon。然后我们实现了两个具体工厂 fantasyFactorysciFiFactory 来创建奇幻世界和科幻世界的角色与武器。

通过这种方式,我们可以很容易地扩展到其他类型的世界,比如古代世界或未来世界,只需要增加相应的具体工厂实现即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甜航一直在

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值