? ? ? ? 简单工厂模式一般在面向对象语言中用得较多,但C语言也可以实现,在做项目的时候可以加入到工程中去,使工程逻辑更加清楚,但工程小的话就没必要用,工程稍微大点使用该设计模式就会很方便,比如我们在使用树莓派或者其它板子做项目时会涉及很多的传感器或者其它电子器件,器件多,代码长,还要考虑代码的稳定性,后期的维护等,像这种情况就可以用这种设计模式来进行写代码。
这种设计方法涉及到了C语言的函数指针,结构体,以及链表的一些相关知识,具体实现方法入下:
现有5个文件:main.c 、led1.c、led2.c、led3.c以及led.h,分别如下
led1.c文件如下:
#include "led.h"
int led1open(int pinNum)
{
digitalWrite(pinNum,LOW);
}
int led1close(int pinNum)
{
digitalWrite(pinNum,HIGH);
}
int ledinit(int PinNum)
{
pinMode(PinNum,OUTPUT);
}
int led1Status(int Ptatus)
{
}
struct Devices led_Init = {
.pinNum = 22,
.devicesName = "led1",
.open = led1open,
.close = led1close,
.devicesInit = ledinit ,
.changeStatus = led1Status
};
struct Devices* addLed1LightToLink(struct Devices *phead)
{
if(phead == NULL){
return &led1; //led1作为头结点
}else{
led1.next = phead;
phead = &led1;
}
}
led1.c文件主要是实现相关的功能,将每个功能都用函数指针进行封装,addLed1LightToLink函数是将该设备加入到链表,方便后面的使用。
led2.cl和ed3.c与上述类似,只是将有led1的地方改为led2和led3即可,引脚号也要改一下。
led.h文件如下
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wiringPi.h>
struct Devices* addLed1LightToLink(struct Devices *phead);
struct Devices* addLed2LightToLink(struct Devices *phead);
struct Devices* addLed3LightToLink(struct Devices *phead);
struct Devices{
char devicesName[128];
int status;
int pinNum;
int (*open)(int PinNum);
int (*close)(int PinNum);
int (*devicesInit)(int PinNum);
int (*readStatus)(int pinNum);
int (*changeStatus)(int status);
bool (*postUrl)(void);
void (*cam)(void);
struct Devices* next;
};
led.h文件主要是声明了Devices 结构体,结构体里面定义了非常多的函数指针,因为模块有很多,不止有led文件,每个模块都可将实现功能部分在自己的文件里面写成如led1.c这样,然后在结构体中定义自己需要的函数指针(led的功能是很简单的,这里只是示范,如果工程很简单的话,就没必要这样做)。
main.c文件如下:
#include "led.h"
struct Devices * findDeviceByname(char * name, struct Devices * phead)
{ //通过设备名字从链表中寻找是否有该设备
struct Devices * tmp = phead;
if (tmp == NULL){
return NULL;
}else{
while (tmp != NULL){
if (strcmp(tmp->devicesName, name) == 0){
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
}
int main()
{
struct Devices * led1 = NULL;
struct Devices * led2 = NULL;
struct Devices * led3 = NULL;
struct Devices * pdeviceHead = NULL; //定义头结点
pdeviceHead = addLed1LightToLink(pdeviceHead); //将led1加入到链表中去
pdeviceHead = addLed2LightToLink(pdeviceHead); //将led2加入到链表中去
pdeviceHead = addLed3LightToLink(pdeviceHead); //将led3加入到链表中去
led1 = findDeviceByname("led1", pdeviceHead); //找led1引脚节点
if(led1 != NULL){ //条件成立则表示从链表中找到了led1节点
while(1){
led1 ->devicesInit(led1 ->pinNum); //初始化led1引脚
led1 ->open(led1 ->pinNum); //打开led1
sleep(1); //延时1s
led1 ->close(led1 ->pinNum); //关闭led1
sleep(1);
}
}
return 0;
}
在main.c文件中先将3个led设备通过调用addLed1LightToLink函数将各个设备添加到链表中去,函数?findDeviceByname 是通过设备名来遍历链表中的设备的,如果找到该设备则可以对其进行下一步操作。
结构体是整个模式的关键,根据外界给定的信息,决定究竟应该执行什么操作,使用工厂模式,用户仅仅需要知道怎样使用接口就可以了,而不用关系内部这些代码究竟是如何创建以及代码逻辑是什么样的,明确了用户和厂家的职责和权利,有利于整个工程体系结构的优化。
|