从建筑设计领域引入到计算机科学中
设计模式一共有23种
代码设计经验的总结,稳定,拓展性更强。一系列编程思想
作用:代码更容易被他人理解、保证代码可靠性、程序的重用性。
详细介绍:[https://www.runoob.com/design-pattern/design-pattern-tutorial.html]:
学习简单工厂模式的目的:为了代码不那么混乱。让代码更稳定,添加功能更方便。
算法:致力于解决问题而非设计问题。
设计模式通常描述了一组相互紧密作用的类与对象。
很多人说,c是一门面向过程的语言,java是一门面向对象的语言;其实这种说法不太对,因为面向过程与面向对象只是一种代码编辑的思想。c也可以面向对象。
类是一种用户自定义的数据类型,也称为类类型。
(C语言中用户自定义的数据类型是结构体。)
对象:类的具象
例子说明:
struct Animal
{
int age;
int sex; //成员属性
void (*peat)();
void (*pbeat)(); //成员方法(一些具体的行为:比如某某人做了某某事)
};
struct Animal dog;
struct Animal cat;
struct Animal person; //对上述一种类的具象(即:对象)
一个简单的面向对象例子
OOP1.c
#include
//类:抽象
struct Animal
{
char name[32];
int age;
int sex;
void (*peat)();
void (*pbeat)();
};
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 cat; //对象:事物的具象
struct Animal dog;
struct Animal person;
dog.peat=dogEat; //对象具体的行为
cat.peat=catEat;
person.peat=personEat;
dog.pbeat=dogBeat;
cat.pbeat=catBeat;
person.pbeat=personBeat;
dogEat();
catEat();
personEat();
dogBeat();
catBeat();
personBeat();
return 0;
}
总结:
类是用户自定义的数据类型。在C语言中是结构体。
类是抽象的,对象能把事物具象化
成员方法是对象的具体行为。做到了事务的具象,每一个对象都有具体的行为
在这里回顾一下函数指针的知识:
每一个函数都有一个入口地址,函数指针是函数的入口地址,而函数名就是函数的地址。
所以把函数指针指向函数名就指向了这个函数。这里说的有点不好,即:声明了这个函数,然后直接调用。
在回顾一下回调函数
定义:
使用者自己定义一个函数,实现这个函数的程序内容,然后把这个函数(入口地址)作为参数传入别人(或系统)的函数中,由别人(或系统)的函数在运行时来调用的函数。
函数是你实现的,但由别人(或系统)的函数在运行时通过参数传递的方式调用,这就是所谓的回调函数。
简单来说,当发生某种事件时,系统或其他函数将会自动调用你定义的一段函数。
示例:
回调函数主要结构有三部分组成:主函数、调用函数和被调函数。C语言中,被调函数通常以函数指针(指向对应函数的入口地址)的形式出现。
//定义回调函数
void PrintfText()
{
printf("Hello World!\n");
}
//定义实现回调函数的"调用函数"
// 参数为函数指针,无参数返回void
void CallPrintfText(void (*callfuct)())
{
callfuct();
}
//实现函数回调
int main(int argc,char* argv[])
{
CallPrintfText(PrintfText);
return 0;
}
struct Animal
{
char name[32];
int age;
int sex;
int others;
void (*peat)();
void (*pbeat)();
};
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 cat={"阿黄",18,‘b’,100,dogeat,dogBeat};
return 0;
}
struct Animal
{
char name[32];
int age;
int sex;
int others;
void (*peat)();
void (*pbeat)();
};
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 cat={
.peat=catEat;
.pbeat=catBeat
};
struct Animal dog={
.peat=dogEat;
.pbeat=dogBeat
};
struct Animal person={
.peat=personEat;
.pbeat=personBeat
};
return 0;
}
工厂模式是最常用的设计模式之一。这种类型的设计模式属于创建型模式,他提供了一种创建对象的最佳方式。
在工厂模式中,我们创建对象时不会对客户端暴露创建逻辑,并且时通过使用一个共同的接口来指向新创建的对象
暴露创建逻辑是:暴露了对象的具体指向和 函数的实现方式。
不在业务中暴露,不在文件中暴露,在其他地方做好,调用。
共同的接口:做好API放到工厂里面,然后mian函数里调用
示例:
dog.c
#include "animal.h"
void dogEat()
{
printf("狗吃屎\n");
}
void dogBeat()
{
printf("咬你\n");
}
struct Animal dog={
.name="huang",
.peat=dogEat,
.pbeat=dogBeat
};
struct Animal* putDogInLink(struct Animal *phead)
{
if(phead==NULL)
{
return &dog;
}
else
{
dog.next=phead;
phead=&dog;
return phead;
}
}
cat.c
#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)
{
return &cat;
}
else
{
cat.next=phead;
phead=&cat;
return phead;
}
}
fish.c
#include "animal.h"
void fishEat()
{
printf("鱼吃料\n");
}
void fishBeat()
{
printf("瞪你\n");
}
struct Animal fish={
.name="fish",
.peat=fishEat,
.pbeat=fishBeat
};
struct Animal* putFishInLink(struct Animal *phead)
{
if(phead==NULL)
{
return &fish;
}
else
{
fish.next=phead;
phead=&fish;
return phead;
}
}
ma.c
#include "animal.h"
void maEat()
{
printf("马吃草\n");
}
void maBeat()
{
printf("踢你\n");
}
struct Animal ma={
.name="ma",
.peat=maEat,
.pbeat=maBeat
};
struct Animal* putMaInLink(struct Animal *phead)
{
if(phead==NULL)
{
return &ma;
}
else
{
ma.next=phead;
phead=&ma;
return phead;
}
}
person.c
#include "animal.h"
void personEat()
{
printf("人吃米\n");
}
void personBeat()
{
printf("打你\n");
}
struct Animal person={
.name="xiaoming",
.peat=personEat,
.pbeat=personBeat
};
struct Animal* putPersonInLink(struct Animal *phead)
{
if(phead==NULL)
{
return &person;
}
else
{
person.next=phead;
phead=&person;
return phead;
}
}
mianPro.c
#include "animal.h"
struct Animal* findUtilName(char *str,struct Animal *phead)
{
struct Animal *ptmp=phead;
if(phead==NULL)
{
printf("链表为空,无法查找\n");
return NULL;
}
while(ptmp!=NULL)
{
// printf("哥,你输的指令是正确的\n");
if(strcmp(ptmp->name,str)==0)
{
return ptmp;
}
ptmp=ptmp->next;
}
printf("你输错了,大哥,指令不对\n");
return NULL;
}
int main()
{
char buf[128]={0};
struct Animal *phead=NULL;
struct Animal *ptmp=NULL;
phead=putCatInLink(phead);
phead=putDogInLink(phead);
phead=putPersonInLink(phead);
phead=putMaInLink(phead);
phead=putFishInLink(phead);
while(1)
{
memset(buf,0,sizeof(buf));
printf("please input Tom,huang,xiaoming,ma,fish;quit exit\n");
scanf("%s",buf);
ptmp=findUtilName(buf,phead);
if(ptmp!=NULL)
{
ptmp->peat();
ptmp->pbeat();
}
if(strcmp(buf,"quit")==0)
{
printf("你已退出\n");
exit(-1);
}
}
return 0;
}
animal.h
#include
#include
#include
struct Animal
{
char name[32];
int age;
int sex;
int others;
void (*peat)();
void (*pbeat)();
struct Animal *next;
};
struct Animal* putCatInLink(struct Animal *phead);
struct Animal* putDogInLink(struct Animal *phead);
struct Animal* putPersonInLink(struct Animal *phead);
struct Animal* putMaInLink(struct Animal *phead);
struct Animal* putFishInLink(struct Animal *phead);
工厂里有猫狗鱼人马,用链表串起来,业务逻辑放在mianpro.c,animal.h暴露出来,然后mianpro调用,这样代码会很稳定,也不乱,一个功能放一个文件