【C语言】面向对象编程–工厂模式
文章目录
- 【C语言】面向对象编程--工厂模式
- 1、什么是工厂模式?
- 2、什么是面向对象编程?
- 2.1 实验一_未用使用工厂模式
- 2.2 实验二_使用工厂模式
- 2.3 实验结果
- 3 总结
1、什么是工厂模式?
声明一个结构体,结构体里面的函数已经被定义,将结构体添在链表里面,这就是一个工厂。然后我们可以根据特定的条件,去工厂里面去找对于功能的结构体(遍历链表),找到以后,拿来执行
- 工厂模式(Factory Pattern)是最常见的设计模式之一。
- 这种类型的设计模式属于创建型模式,它提供了一种创建对象的(最佳)方式。
- 在工厂模式中,他们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的端口来指向新创建的对象。
2、什么是面向对象编程?
对于这个问题,我们可以对比下文程序结构的区别来体会。
2.1 实验一_未用使用工厂模式
//OOP.c
#include <stdio.h>
//类:抽象 模板
struct Animal {
char name[128];
int age;
int sex;
int others;
void (*peat)();//函数指针,指向函数的指针
void (*pbeat)();
void (*test)();//结构体内的元素不一定全都会被用到
};
//定义函数,后续将传递给结构体中的函数指针
void dogEat()
{
printf("狗吃骨头\n");
}
void catEat()
{
printf("猫吃鱼\n");
}
void personEat()
{
printf("人吃饭\n");
}
void dogBeat()
{
printf("咬你小弟弟\n");
}
void catBeat()
{
printf("抓你小弟弟\n");
}
void personBeat()
{
printf("猴子偷桃\n");
}
int main()
{
//以前我们用结构体,喜欢这样用
struct Animal dog1 = { "小柴",1,1,100,dogEat,dogBeat };
//name[128]; age; sex; others; (*peat)(); (*pbeat)();(*test)();
/*
有时候我们并不想给结构体内所有元素赋值,只给个别赋值,就可以
*/
//我们可以这样写:
struct Animal dog = {
.peat = dogEat, //将这个函数的地址给 peat (peat是一个指针)
.pbeat = dogBeat
};
struct Animal cat = {
.peat = catEat,
.pbeat = catBeat
};
struct Animal person = {
.peat = personEat,
.pbeat = personBeat
};//对象 是事物的具象
printf("==============\n");
dog.peat();//执行
cat.peat();
person.peat();
dog.pbeat();
cat.pbeat();
person.pbeat();
return 0;
}
2.2 实验二_使用工厂模式
- 把同一个类并列的 功能函数 赋值到一个结构体里的函数指针中,结构体里面的函数已经被定义,将结构体通过头插法 形成链表,这就是一个工厂
下面用一个导图来直观的描述实验一工厂模式的框架
- 各文件程序
//Animal.h 头文件
#include <stdio.h>
struct Animal {
char name[128];
int age;
int sex;
int others;
void (*peat)();//函数指针,指向函数的指针
void (*pbeat)();
void (*test)();
struct Animal* next;
};
struct Animal* putCatInLink(struct Animal* phead);//链接结构体的函数
struct Animal* putDogInLink(struct Animal* phead);
struct Animal* putPersonInLink(struct Animal* phead);
//类1 cat.c
#include <stdio.h>
#include "Animal.h"
void catEat()
{
printf("猫吃鱼\n");
}
void catBeat()
{
printf("抓你小弟弟\n");
}
struct Animal cat = {
.name = "Tom",
.peat = catEat,
.pbeat = catBeat
};
struct Animal* putCatInLink(struct Animal *phead) //头插法
{
if (phead == NULL)
{
phead = &cat; //将 结构体cat 的地址传给 指针phead
return phead;
}
else
{
cat.next = phead; //cat 的下一个是之前的头
phead = &cat; //cat 变成新的头
return phead;
}
}
//类2 dog.c
#include <stdio.h>
#include "Animal.h"
void dogEat()
{
printf("狗吃骨头\n");
}
void dogBeat()
{
printf("咬你小弟弟\n");
}
struct Animal dog = {
.name = "xiaohuang",
.peat = dogEat,
.pbeat = dogBeat
};
struct Animal* putDogInLink(struct Animal* phead) //头插法
{
if (phead == NULL)
{
phead = &dog;
return phead;
}
else
{
dog.next = phead; //dog 的下一个是之前的头
phead = &dog; //fog 变成新的头
return phead;
}
}
//类3 person.c
#include <stdio.h>
#include "Animal.h"
void personEat()
{
printf("人吃饭\n");
}
void personBeat()
{
printf("猴子偷桃\n");
}
struct Animal person = {
.name = "tp",
.peat = personEat,
.pbeat = personBeat
};
struct Animal* putPersonInLink(struct Animal* phead) //头插法
{
if (phead == NULL)
{
phead = &person;
return phead;
}
else
{
person.next = phead; //person 的下一个是之前的头
phead = &person; //person这个结构体的地址传给phead指针 变成新的头
return phead;
}
}
- 主函数
//main.c
#include "animal.h"
#include <string.h>
struct Animal* findUtilByName(char* str, struct Animal* phead)
{
struct Animal* tmp = phead;
if (phead == NULL)
{
printf("空\n");
return NULL;
}
else
{
while (tmp != NULL)
{
if (strcmp(tmp->name, str) == 0)
{
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
}
int main()
{
char buf[128] = {'\0'};
struct Animal *phead = NULL;
struct Animal* ptmp;
phead = putCatInLink(phead);//把cat结构体放在了链表里面
phead = putDogInLink(phead);//把dog结构体放在了链表里面
phead = putPersonInLink(phead);//把person结构体放在了链表里面
while (1)
{
//根据用户输入的名字,找到相应的结构体
//根据特定的条件,去工厂里面去找,找到东西以后,拿来执行
printf("请输入你:Tom、xiaohuang,tp\n");
scanf_s("%s", buf, sizeof(buf));//注意:VS studio中scanf_s的用法
ptmp = findUtilByName(buf, phead);
printf("=========\n");
if (ptmp != NULL)
{
ptmp->pbeat();//点操作符用于直接访问结构体变量的成员,而箭头操作符用于通过指针间接访问结构体变量的成员
ptmp->peat();
}
}
return 0;
}
2.3 实验结果
3 总结
-
大家可以有疑问,怎么实验1中使用了工厂模式后的代码量和文件数比未使用的时候多?这不是增加了阅读代码的复杂度了吗?
-
如果是针对简单的小项目,确实是这样子的,但是如果是针对几万行的大型项目,利用工厂模式就会显得方便许多;在我们想对项目中的”类“进行增删改查时,我们不用改动main函数中while里面的业务代码,只需要加个类的.c 文件,声名一下,然后在main函数中连接到链表,就完事了,大大的提高程序的维护效率。
欢迎大家一起交流讨论!