设计模式(简单工厂模式)
1.什么是设计模式
从建筑设计领域引入到计算机科学中
设计模式一共有23种
代码设计经验的总结,稳定,拓展性更强。一系列编程思想
作用:代码更容易被他人理解、保证代码可靠性、程序的重用性。
详细介绍:[https://www.runoob.com/design-pattern/design-pattern-tutorial.html]:
学习简单工厂模式的目的:为了代码不那么混乱。让代码更稳定,添加功能更方便。
算法:致力于解决问题而非设计问题。
设计模式通常描述了一组相互紧密作用的类与对象。
很多人说,c是一门面向过程的语言,java是一门面向对象的语言;其实这种说法不太对,因为面向过程与面向对象只是一种代码编辑的思想。c也可以面向对象。
2.类和对象
-
类是一种用户自定义的数据类型,也称为类类型。
-
(C语言中用户自定义的数据类型是结构体。)
-
对象:类的具象
例子说明:
struct Animal
{int age;int sex; //成员属性void (*peat)();void (*pbeat)(); //成员方法(一些具体的行为:比如某某人做了某某事)
};struct Animal dog;
struct Animal cat;
struct Animal person; //对上述一种类的具象(即:对象)
一个简单的面向对象例子
OOP1.c
#include<stdio.h>//类:抽象
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;
}
2.2C结构体新玩法
2.2.1常用的方法
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;
}
2.2.2新玩法(内核常用)
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;
}
3.工厂模式
3.1.什么是工厂模式
工厂模式是最常用的设计模式之一。这种类型的设计模式属于创建型模式,他提供了一种创建对象的最佳方式。
在工厂模式中,我们创建对象时不会对客户端暴露创建逻辑,并且时通过使用一个共同的接口来指向新创建的对象
暴露创建逻辑是:暴露了对象的具体指向和 函数的实现方式。
不在业务中暴露,不在文件中暴露,在其他地方做好,调用。
共同的接口:做好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<stdlib.h>
#include<stdio.h>
#include<string.h>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调用,这样代码会很稳定,也不乱,一个功能放一个文件