设计模式-C版本-工厂模式

C版本

工厂模式的实现步骤如下:

  • 定义一个抽象产品接口,用于定义一组产品的通用行为。
  • 定义一个具体产品类,实现抽象产品接口,用于提供具体的产品实现。
  • 定义一个抽象工厂接口,用于定义工厂类应该实现的方法。
  • 定义一个具体工厂类,实现抽象工厂接口,用于创建具体的产品对象。
  • 在客户端代码中使用工厂类创建具体的产品对象。

示例代码一

Code
/*
	1.简单工厂模式:struct写法
	https://developer.aliyun.com/article/1171580
*/
typedef enum 
{
	SUV,
	BUS,
	CAR,
}CAR_TYPE;
typedef struct 
{
	int price;
	char * type;
}CAR_MODEL;
CAR_MODEL * car_factory(CAR_TYPE type)
{
	CAR_MODEL *car = (CAR_MODEL *)malloc(sizeof(CAR_MODEL));
	if (car == NULL)
		return NULL;
	switch (type)
	{
		case SUV:
			car->price = 170000;
			car->type = "SUV car";
			break;
		case BUS:
			car->price = 150000;
			car->type = "BUS car";
			break;
		case CAR:
			car->price = 120000;
			car->type = "CAR car";
			break;
		default:
			printf("Invalid car\n");
			free(car);
			break;
	}
	return car;
}
void simple_factory(void)
{
	CAR_MODEL * A = car_factory(SUV);
	printf("A price:%d, model:%s\r\n", A->price, A->type);
	CAR_MODEL * B = car_factory(BUS);
	printf("B price:%d, model:%s\r\n", B->price, B->type);
	CAR_MODEL * C = car_factory(CAR);
	printf("C price:%d, model:%s\r\n", C->price, C->type);
	CAR_MODEL * invalid = car_factory(11);
	printf("invalid price:%d, model:%s\r\n", invalid->price, invalid->type);
	free(A);
	free(B);
	free(C);
	return ;
}

示例代码二

Code
/*
	2.简单工厂模式:typedef写法
	https://zhuanlan.zhihu.com/p/613368234
*/
// 水果类型枚举定义
typedef enum FruitType
{
	Apple = 1,
	Banana,
	Pear
}FruitType_;
// 通用结构体
typedef struct FRUIT
{
	void (* show)(void);
	void (* eat)(int);
	char *name;
}Fruit_t;
static void show_apple(void)
{
	printf("show_apple\r\n");
}
static void eat_apple(int n)
{
	printf("eat_apple %d\r\n", n);
}
// 构造函数-apple
Fruit_t * constructor_fruit_apple(void *obj)
{
	Fruit_t *m_fruit = (Fruit_t *)malloc(sizeof(Fruit_t));
	m_fruit->name = "Apple";
	m_fruit->show = show_apple;
	m_fruit->eat  = eat_apple;
	return m_fruit;
};
static void show_banana(void)
{
	printf("show_banana\r\n");
}
static void eat_banana(int n)
{
	printf("eat_banana %d\r\n", n);
}
Fruit_t * constructor_fruit_banana(void *obj)
{
	// Fruit_t m_fruit;	// 局部变量不能直接return,需要malloc申请内存
	Fruit_t *m_fruit = (Fruit_t *)malloc(sizeof(Fruit_t));
	m_fruit->name = "Banana";
	m_fruit->show = show_banana;
	m_fruit->eat = eat_banana;
	return m_fruit;
}
static void show_pear(void)
{
	printf("show_pear\r\n");
}
static void eat_pear(int n)
{
	printf("eat_pear %d\r\n", n);
}
void constructor_fruit_pear(Fruit_t * m_fruit)
{
	m_fruit->name = "Pear";
	m_fruit->show = show_pear;
	m_fruit->eat = eat_pear;
	return ;
}
// 简单工厂
Fruit_t * simple_factory_fruit(enum FruitType type)
{
	Fruit_t * m_fruit = (Fruit_t *)malloc(sizeof(Fruit_t));
	switch (type)
	{
		case Apple:
			m_fruit = constructor_fruit_apple(NULL);
			break;
		case Banana:
			m_fruit = constructor_fruit_banana(NULL);
			break;
		case Pear:
			constructor_fruit_pear(m_fruit);
			break;
		default:
			printf("error type\n");
			break;
	}
	return m_fruit;
}
void fruit_main_func(void)
{
	Fruit_t * A = NULL;
	A = simple_factory_fruit(Apple);
	A->show();
	A->eat(1);
	Fruit_t * B = NULL;
	B = simple_factory_fruit(Banana);
	B->show();
	B->eat(1);
	Fruit_t * C = NULL;
	C = simple_factory_fruit(Pear);
	C->show();
	C->eat(1);
	free(A);
	free(B);
	free(C);
	return ;
}

示例代码三

Code
/*
	4.工厂模式:列表方法
	https://blog.csdn.net/mirco_mcu/article/details/114684142
*/
void eeprom_init(void)
{
    printf("初始化 EEPROM\n");
}
void eeprom_open(void)
{
    printf("启用 EEPROM\n");
}
void eeprom_write(int addr, char *data, int len)
{
    printf("向EEPROM 地址:%x 写入%d 字节数据:%s\n", addr, len, (char *)data);
}
void flash_init(void)
{
    printf("初始化 FLASH\n");
}
void flash_open(void)
{
    printf("启用 FLASH\n");
}
void flash_write(int addr, char *data, int len)
{
    printf("向FLASH 地址:%x 写入%d 字节数据:%s\n", addr, len, (char *)data);
}
typedef struct STORAGE
{
	char *name;
	void (* init)(void);
	void (* open)(void);
	void (* write)(int, char *, int);
}storage_t;
storage_t storage_list[] =
{
	{"eeprom", eeprom_init, eeprom_open, eeprom_write},
	{"flash", flash_init, flash_open, flash_write}
};
storage_t *factory_creat(char *name)
{
	int i;
	for (i = 0; i < sizeof(storage_list) / sizeof(storage_list[0]); i++)
	{
		if (0 == strcmp(name, storage_list[i].name))
		{
			storage_list[i].init();
			storage_list[i].open();
			return &storage_list[i];
		}
	}
	return NULL;
}
void factory_main_func(void)
{
	char *str[] = {"EEPROM", "FLASH"};
	storage_t *byte_date = factory_creat("eeprom");
	storage_t *sector_date = factory_creat("flash");
	byte_date->write(0x0100, str[0], sizeof(str[0]));
	sector_date->write(0x0200, str[1], sizeof(str[1]));
}

示例代码四

Code
/*
	5.工厂模式:女娲造人篇
*/
typedef enum manType_
{
	Yellow = 1,
	Black,
	White,
}manType;
// 抽象种人
typedef struct AbstractHuman_
{
	void (*Get_Corlor)(void);
	void (* Talk_Language)(void);
}AbstractHuman;
// yellow Base版
void Get_Corlor_Y(void)
{
	printf("Get_Corlor_Y\r\n");
	// todo
}
// yellow Base版
void Talk_Language_Y(void)
{
	printf("Talk_Language_Y\r\n");
	// todo
}
// 为什么要在这里实例化?不应该是抽象定义吗?
// 既然已经实例化了,后面不能按之前写了
// 他这里定义一个原始种人,后面直接用它传参取地址
// 定义yellow人的Base版
AbstractHuman YellowHuman = {
	.Get_Corlor = Get_Corlor_Y,
	.Talk_Language = Talk_Language_Y,
};
// white Base版
void Get_Corlor_W(void)
{
	printf("Get_Corlor_W\r\n");
	// todo
}
void Talk_Language_W(void)
{
	printf("Talk_Language_W\r\n");
	// todo
}
// 定义white人的Base版
AbstractHuman WhiteHuman = {
	.Get_Corlor = Get_Corlor_W,
	.Talk_Language = Talk_Language_W,
};
// 抽象工厂
typedef struct AbstractFactory_
{
	// 注意这里的星号
	AbstractHuman * (*Human_Create_Factory)(AbstractHuman *pHuman);
}AbstractFactory;
// 具体工厂-Base版
AbstractHuman * Create_Human(AbstractHuman *pHuman)
{
	printf("Create_Human\r\n");
	if (pHuman == NULL)
		return NULL;
	AbstractHuman *human = (AbstractHuman *)malloc(sizeof(AbstractHuman));
	if (human == NULL)
		return NULL;
	memset(human, 0, sizeof(human));
	human->Get_Corlor = pHuman->Get_Corlor;
	human->Talk_Language = pHuman->Talk_Language;
	return human;
}
// 具体工厂定义
AbstractFactory Human_Factory = {
	.Human_Create_Factory = Create_Human,
};
// 主函数
void NvWa_main_function(void)
{
	AbstractFactory YYLu = Human_Factory;
	AbstractHuman * yellowMan = YYLu.Human_Create_Factory(&YellowHuman);
	if (yellowMan != NULL)
	{
		yellowMan->Get_Corlor();
		yellowMan->Talk_Language();	
		free(yellowMan);
	}
	AbstractHuman * whiteMan = YYLu.Human_Create_Factory(&WhiteHuman);
	if (whiteMan != NULL)
	{
		whiteMan->Get_Corlor();
		whiteMan->Talk_Language();	
		free(whiteMan);
	}
}

参考链接

posted @ 2024-02-25 12:05  starc再起航  阅读(10)  评论(0编辑  收藏  举报