用C语言实现简单工厂模式!

用C语言实现简单工厂模式!

一.背景介绍

在我们的印象中,设计模式是由面向对象的语言(C++、JAVA)才能完成的,而C语言是面向过程的语言,不能实现设计模式。C语言中有 函数指针回调函数 等机制,使用这些机制便能写出面向对象的优秀程序。

LINUX操作系统,采用的就是C语言写的,但是里面很多模块实现都是通过面向对象的设计方式实现的,这也是很多人初看Linux源码看得云里雾里的原因。

面向过程(Procedure Oriented 简称 PO): 把事情拆分成几个步骤(相当于拆分成一个个的方法和数据),然后按照一定的顺序执行。

面向对象(Object Oriented 简称 OO): 面向对象会把事物抽象成对象的概念,先抽象出对象,然后给对象赋一些属性和方法,然后让每个对象去执行自己的方法。

二.设计实现

在C++中实现设计模式主要是通过virtual关键字修饰的虚函数来实现的,在C语言中没有这个操作,但是我们可以通过指针函数加结构体进行实现。我们先简单了解一下指针函数:

typedef void (*pfunc)(int); //此处定义了pfunc这个函数指针

//定义一个test_func函数,与pfunc的返回类型和参数是一致的,只有名字不同
//若不一致则不能定义pfunc的指针指向test_func
void test_func(int id)      
{   
    printf("id=%d \n", id);
}

//使用func指向test_func()
pfunc func = test_func;

//调用func(id) 与 test_func(id)实现的功能一致
func(1);//即可使用

//与结构体结合
typedef struct func_t
{
    void (*func)(int id);
}func_t;

func_t f;
f.func = test_func; //结构体的函数指针指向test_func()
f.func(1); //调用结构体的函数指针,与调用test_func(1)效果一致

//通过上述例子,我们可以看到通过结构体+函数指针可以实现封装信息并指向另外一个函数
//有了这个特性我们可以实现一个简单工厂模式

本设计实现一个简单的工厂模式,一个生产不同种类水果的工厂。每种水果有两个属性show() eat(),实现apple、banana、pear这3种水果。

//设计抽象定义接口
//定义的抽象的水果接口
typedef struct Ifruit_t
{
    void (*show)(void* obj);  //显示信息
    void (*eat)(void* obj);   //怎么吃
    void *obj;                //指向当前的结构体
}Ifruit_t;

下面程序是香蕉水果相关的定义, 另外的 苹果与梨 定义与这个几乎完全一致,此处考虑篇幅问题,不全部贴出来了。

//------------------------------------------------
//实现香蕉相关的定义
//------------------------------------------------
typedef struct banana_t             //与Ifruit_t的定义一致
{
    void (*show)(void* obj);        //显示信息
    void (*eat)(void* obj);         //怎么操作才能吃
    void *obj;                      //指向当前的结构体
}banana_t;

static void banana_show(void* obj)   //使用static修饰,避免被外部直接调用
{
    printf("我是香蕉!\n");
}

static void banana_eat(void* obj)  //使用static修饰,避免被外部直接调用
{
    printf("操作: 先剥掉皮,再吃!\n");
}
//香蕉的构造函数
banana_t* constructor_banana(void)  //不使用static修饰,让外部直接调用
{
    banana_t* obj = (banana_t*)malloc(sizeof(banana_t));
    obj->show = banana_show;        //给指针函数赋值,后面才能被调用
    obj->eat = banana_eat;//给指针函数赋值,后面才能被调用
    obj->obj = obj;                 //obj指向当前结构体指针
    return obj;
}

工厂实现的函数 如下:

enum FruitType  //枚举类型
{
    APPLE,      //苹果
    BANANA,     //香蕉
    PEAR,       //梨
};

Ifruit_t* factor_create_fruit(enum FruitType type) //工厂:生成水果的
{
    Ifruit_t *fruit=NULL;

    switch (type)
    {
    case APPLE:
        fruit = (Ifruit_t *)constructor_apple();
        printf("工厂: 生产苹果!\n");
        break;
    case BANANA:
        fruit = (Ifruit_t *)constructor_banana();
        printf("工厂: 生产香蕉!\n");
        break;
    case PEAR:
        fruit = (Ifruit_t *)constructor_pear();
        printf("工厂: 生产梨!\n");
        break;
    default:
        break;
    }
    return fruit;
}

main使用流程 如下。工厂设计模式它的优势是易于扩展,此处我们实现了香蕉、苹果、梨种水果,当业务中需要西瓜时,我们指向写一个西瓜相关的结构体并实现对应函数,实现方式和上面banana实现方式一致,而对于西瓜的使用依旧是如下调用 fruit->show(NULL); fruit->eat(NULL);,这样我们主体的业务逻辑便能完成以较小的改动来添加一个新的模块功能。

int main(void)
{
    Ifruit_t *fruit=NULL;

    fruit = factor_create_fruit(APPLE); //生成苹果
    //每一次有新的水果添加进来,步骤都和下面一样的,易于扩展
    fruit->show(NULL);                  //显示苹果
    fruit->eat(NULL);                   //操作苹果
    free(fruit);                        //不使用了,释放资源
    printf("\n");

    fruit = factor_create_fruit(BANANA);
    fruit->show(NULL);
    fruit->eat(NULL);
    free(fruit);
    printf("\n");

    
    fruit = factor_create_fruit(PEAR);
    fruit->show(NULL);
    fruit->eat(NULL);
    free(fruit);

    return 0;
}

三.运行测试

运行信息如下:
在这里插入图片描述

四.总结

虽然C语言是面向过程的编程语言,但是我们在设计程序的时候,可以考虑用面向对象的方式去设计,这样提高我们程序的“高内聚、低耦合”特性,便于维护。

想要整个工程文件的小伙伴:关注微信公众号【Linux编程用C】,在微信公众号回复 factor即可获取

我是小C,欢迎大家关注、点赞支持,我们一起交流讨论学习!

PS:若大家想看C语言版本的其他设计模式,

请大家 点赞! 转发!关注!催更吧~~

抽象工厂模式是一种创建型设计模式,它允许客户端代码使用抽象接口来创建一组相关或依赖对象,而无需指定其具体类。 在C语言中,可以使用函数指针来模拟抽象类和虚函数,从而实现抽象工厂模式。 下面是一个简单的示例,演示如何使用C语言实现抽象工厂模式: ```c #include <stdio.h> // 定义抽象产品1接口 typedef struct { void (*operation1)(void); } AbstractProduct1; // 定义抽象产品2接口 typedef struct { void (*operation2)(void); } AbstractProduct2; // 定义抽象工厂接口 typedef struct { AbstractProduct1* (*createProduct1)(void); AbstractProduct2* (*createProduct2)(void); } AbstractFactory; // 定义具体产品1A typedef struct { AbstractProduct1 base; } Product1A; // 实现具体产品1A的操作1 static void operation1A(void) { printf("Product 1A Operation 1\n"); } // 定义具体产品2A typedef struct { AbstractProduct2 base; } Product2A; // 实现具体产品2A的操作2 static void operation2A(void) { printf("Product 2A Operation 2\n"); } // 定义具体工厂A typedef struct { AbstractFactory base; } FactoryA; // 实现具体工厂A的createProduct1函数 static AbstractProduct1* createProduct1A(void) { Product1A* product = malloc(sizeof(Product1A)); product->base.operation1 = operation1A; return &product->base; } // 实现具体工厂A的createProduct2函数 static AbstractProduct2* createProduct2A(void) { Product2A* product = malloc(sizeof(Product2A)); product->base.operation2 = operation2A; return &product->base; } // 定义具体产品1B typedef struct { AbstractProduct1 base; } Product1B; // 实现具体产品1B的操作1 static void operation1B(void) { printf("Product 1B Operation 1\n"); } // 定义具体产品2B typedef struct { AbstractProduct2 base; } Product2B; // 实现具体产品2B的操作2 static void operation2B(void) { printf("Product 2B Operation 2\n"); } // 定义具体工厂B typedef struct { AbstractFactory base; } FactoryB; // 实现具体工厂B的createProduct1函数 static AbstractProduct1* createProduct1B(void) { Product1B* product = malloc(sizeof(Product1B)); product->base.operation1 = operation1B; return &product->base; } // 实现具体工厂B的createProduct2函数 static AbstractProduct2* createProduct2B(void) { Product2B* product = malloc(sizeof(Product2B)); product->base.operation2 = operation2B; return &product->base; } int main() { // 创建具体工厂A FactoryA factoryA; factoryA.base.createProduct1 = createProduct1A; factoryA.base.createProduct2 = createProduct2A; // 使用具体工厂A创建产品 AbstractProduct1* product1A = factoryA.base.createProduct1(); AbstractProduct2* product2A = factoryA.base.createProduct2(); // 调用产品的操作 product1A->operation1(); product2A->operation2(); // 创建具体工厂B FactoryB factoryB; factoryB.base.createProduct1 = createProduct1B; factoryB.base.createProduct2 = createProduct2B; // 使用具体工厂B创建产品 AbstractProduct1* product1B = factoryB.base.createProduct1(); AbstractProduct2* product2B = factoryB.base.createProduct2(); // 调用产品的操作 product1B->operation1(); product2B->operation2(); return 0; } ``` 在上面的示例中,我们定义了抽象产品1和抽象产品2的接口,以及抽象工厂的接口。然后使用具体的产品和工厂来实现这些接口。最后,我们可以使用具体工厂来创建具体产品,并调用它们的操作。 需要注意的是,在C语言中,需要手动管理内存,因此需要在使用完产品后释放它们的内存。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值