文章目录
前言
回顾之前我们写的C语言代码,不管是学生成绩管理系统还是FTP服务器,代码逻辑都非常混乱,写着写着就会出错,也不好调试,代码的可扩展性较差。这时候就需要借助设计模式了。
设计模式是代码设计经验的总结,是一系列的编程思想,使得代码的稳定性、拓展性更强。
一、简单工厂模式
简单工厂模式是23种设计模式的一种,是最常用的设计模式之一,这种类型的模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
比如只需要知道水果的名字即可得到相应的水果:
二、简单工厂模式代码示例
将“猫”、“狗”、“人”这些类封装起来,放进工厂,做成链表,我们只需要在主函数中输入相应参数,就能实现相关类的访问,实现相应功能。
animal.h
//animal.h
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct animal
{
char name[28];
int age;
int sex;
void (*peat)();//函数指针
void (*pbeat)();
struct animal *next;
};
void catEat();
void catBeat();
void dogEat();
void dogBeat();
void personEat();
void personBeat();
struct animal* findObjectByName(struct animal* phead, char* str);
struct animal* putCatInLink(struct animal *phead);
struct animal* putDogInLink(struct animal *phead);
struct animal* putPersonInLink(struct animal *phead);
//这些其实应该在单独的.h文件中声明,但因为文件比较简单,这里为了方便直接在一个.h文件中进行
cat.c
#include "animal.h"
void catEat()
{
printf("cat eat fish\n");
}
void catBeat()
{
printf("cat scratch you\n");
}
struct animal cat =
{
.name = "Tom",
.peat = catEat,
.pbeat = catBeat
};
//内核中结构体定义的一种常见方式,注意这种赋值方式哦!
//每个成员后面是逗号隔开,最后一个后面没有逗号,结构体大括号外面的分号不要忘了
struct animal* putCatInLink(struct animal *phead)
{
if(phead == NULL)
{
phead = &cat;
return phead;
}else
{
cat.next = phead;
phead = &cat;
return phead;
}
}//头插法将cat加入链表
dog.c
#include "animal.h"
void dogEat()
{
printf("dog eat shit\n");
}
void dogBeat()
{
printf("dog bite you\n");
}
struct animal dog =
{
.name = "ahuang",
.peat = dogEat,
.pbeat = dogBeat
};//内核中结构体定义的一种常见方式
struct animal* putDogInLink(struct animal *phead)
{
if(phead == NULL)
{
phead = &dog;
return phead;
}else
{
dog.next = phead;
phead = &dog;
return phead;
}
}//头插法将dog加入链表
person.c
#include "animal.h"
void personEat()
{
printf("person eat rice\n");
}
void personBeat()
{
printf("human fight\n");
}
struct animal person =
{
.name = "xiaoming",
.peat = personEat,
.pbeat = personBeat
};//内核中结构体定义的一种常见方式
struct animal* putPersonInLink(struct animal *phead)
{
if(phead == NULL)
{
phead = &person;
return phead;
}else
{
person.next = phead;
phead = &person;
return phead;
}
}//头插法将person加入链表
find.c
#include "animal.h"
struct animal* findObjectByName(struct animal* phead, char* str)
{
struct animal *ptemp = phead;
if(phead = NULL)
{
printf("link list is nothing");
exit(-1);
}else
{
while(ptemp != NULL)
{
if(strcmp(ptemp->name,str) == 0)
{
return ptemp;
}
ptemp = ptemp->next;//遍历链表
}
return NULL;
}
}
mainPro.c
#include "animal.h"
int main()
{
char buf[28] = {
'\0'};
struct animal *phead = NULL;
struct animal *ptemp = NULL;
phead = putCatInLink(phead);
phead = putDogInLink(phead);
phead = putPersonInLink(phead);
//将所有对象加入链表,构成工厂
while(1)
{
printf("please input the object:Tom ahuang xiaoming\n");
scanf("%s",buf);
ptemp = findObjectByName(phead,buf);
if(ptemp == NULL)
{
printf("no such object\n");//没有这个对象
}else
{
ptemp->peat();
ptemp->pbeat();
}
memset(buf,'\0',sizeof(buf));
}
return 0;
}
Makefile文件:
main: mainPro.o cat.o dog.o person.o find.o
gcc -o main mainPro.o cat.o dog.o person.o find.o
mainPro.o: mainPro.c
gcc -c mainPro.c
cat.o: cat.c
gcc -c cat.c
dog.o: dog.c
gcc -c dog.c
person.o: person.c
gcc -c person.c
find.o: find.c
gcc -c find.c
clean:
rm *.o
rm main
测试:
调试过程:
在Linux下编译时老是报以下错误:
后来在网上查了大半圈,以为是哪里的函数声明或者实现有问题,结果都没有问题,最后发现是 main 写成了 mian ,我™真是个傻子。