创建型模式
工厂方法模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。
为什么需要工厂方法模式?
看一个 “没有工厂模式” 的痛点场景:
假设你在开发一个游戏,最初只有 “战士” 一种角色,代码可能这样写:
// 早期代码:直接在客户端创建对象
void startGame() {// 直接new具体角色Warrior* warrior = new Warrior(); warrior->attack();// ...
}
但随着游戏迭代,需要添加 “法师” 角色,你不得不修改客户端代码:
// 迭代后:客户端代码被迫修改
void startGame(std::string roleType) {Character* character;// 客户端需要知道所有具体角色的类型if (roleType == "warrior") {character = new Warrior();} else if (roleType == "mage") { // 新增逻辑character = new Mage();}character->attack();// ...
}
继续迭代添加 “弓箭手”“刺客” 时,客户端代码会被反复修改,最终变得臃肿且脆弱。
工厂方法优点
1.解耦对象创建与使用
2.符合开闭原则
新增产品时,只需添加对应的具体产品类(如Assassin)和具体工厂类(如AssassinFactory),无需修改现有工厂和客户端代码。例如要增加 “刺客” 角色,原有的战士、法师工厂代码完全不用动。
3.单一职责原则
每个具体工厂只负责创建一种产品(如WarriorFactory
只创建战士),职责清晰,避免了一个类承担过多创建逻辑。
4.支持多态创建
客户端可以通过相同的接口(抽象工厂)创建不同类型的产品。
5.便于扩展和测试
示例
#include <iostream>
#include <string>
#include <memory>// 产品接口:游戏角色
class Character {
public:virtual ~Character() = default;virtual void attack() const = 0; // 攻击方法virtual void defend() const = 0; // 防御方法virtual std::string getName() const = 0; // 获取角色名称
};// 具体产品1:战士(近战高防御)
class Warrior : public Character {
public:void attack() const override {std::cout << "战士挥舞大剑,进行猛烈劈砍!" << std::endl;}void defend() const override {std::cout << "战士举起盾牌,形成坚固防御!" << std::endl;}std::string getName() const override {return "钢铁战士";}
};// 具体产品2:法师(远程魔法攻击)
class Mage : public Character {
public:void attack() const override {std::cout << "法师吟唱咒语,释放火球术!" << std::endl;}void defend() const override {std::cout << "法师召唤魔法屏障,抵御伤害!" << std::endl;}std::string getName() const override {return "元素法师";}
};// 具体产品3:弓箭手(远程物理攻击)
class Archer : public Character {
public:void attack() const override {std::cout << "弓箭手拉满长弓,射出精准箭矢!" << std::endl;}void defend() const override {std::cout << "弓箭手快速后跳,闪避攻击!" << std::endl;}std::string getName() const override {return "精灵弓箭手";}
};// 抽象工厂:角色创建工厂
class CharacterFactory {
public:virtual ~CharacterFactory() = default;virtual std::unique_ptr<Character> createCharacter() = 0; // 工厂方法:创建角色
};// 具体工厂1:战士工厂
class WarriorFactory : public CharacterFactory {
public:std::unique_ptr<Character> createCharacter() override {std::cout << "=== 战士工厂创建角色 ===" << std::endl;return std::make_unique<Warrior>(); // 创建战士}
};// 具体工厂2:法师工厂
class MageFactory : public CharacterFactory {
public:std::unique_ptr<Character> createCharacter() override {std::cout << "=== 法师工厂创建角色 ===" << std::endl;return std::make_unique<Mage>(); // 创建法师}
};// 具体工厂3:弓箭手工厂
class ArcherFactory : public CharacterFactory {
public:std::unique_ptr<Character> createCharacter() override {std::cout << "=== 弓箭手工厂创建角色 ===" << std::endl;return std::make_unique<Archer>(); // 创建弓箭手}
};// 客户端:游戏角色选择系统
class GameSystem {
public:// 根据选择的工厂创建角色并执行操作static void playWithCharacter(CharacterFactory& factory) {auto character = factory.createCharacter(); // 通过工厂获取角色std::cout << "创建了角色:" << character->getName() << std::endl;// 角色执行战斗操作character->attack();character->defend();std::cout << std::endl;}
};int main() {// 玩家选择战士WarriorFactory warriorFactory;GameSystem::playWithCharacter(warriorFactory);// 玩家选择法师MageFactory mageFactory;GameSystem::playWithCharacter(mageFactory);// 玩家选择弓箭手ArcherFactory archerFactory;GameSystem::playWithCharacter(archerFactory);// 如需添加新角色(如刺客),只需新增:// 1. Assassin类(实现Character接口)// 2. AssassinFactory类(实现CharacterFactory接口)// 无需修改现有代码,符合开闭原则return 0;
}
c语言的工厂方法模式
我们在用keil5开发单片机程序时候,可以也学着这种方法去开发。这样结构清晰。具体就是将共有的部分抽离出来,做结构体。功能的实现封装函数指针,放入结构体中。这样子对于多模块的使用,以及后续拓展都有很好的便捷性。
给出示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// -------------------------- 外设抽象产品 --------------------------
// 外设抽象接口(相当于抽象类)
typedef struct Peripheral {void (*enable)(struct Peripheral*); // 使能设备void (*disable)(struct Peripheral*); // 禁用设备void (*set_param)(struct Peripheral*, int param, int value); // 设置参数void (*destroy)(struct Peripheral*); // 销毁资源const char* name; // 设备名称// 可以添加通用属性,如设备地址、状态等int address;int status; // 0: 禁用, 1: 使能
} Peripheral;// -------------------------- 具体产品实现(电机) --------------------------
// 电机特有参数定义
#define MOTOR_PARAM_SPEED 1 // 速度参数
#define MOTOR_PARAM_DIRECTION 2 // 方向参数// 电机使能
static void motor_enable(Peripheral* dev) {dev->status = 1;printf("[%s] 已使能 (地址: 0x%02X) - 开始运转\n", dev->name, dev->address);
}// 电机禁用
static void motor_disable(Peripheral* dev) {dev->status = 0;printf("[%s] 已禁用 (地址: 0x%02X) - 停止运转\n", dev->name, dev->address);
}// 电机参数设置(速度0-100,方向0-1)
static void motor_set_param(Peripheral* dev, int param, int value) {if (dev->status != 1) {printf("[%s] 未使能,无法设置参数\n", dev->name);return;}switch(param) {case MOTOR_PARAM_SPEED:printf("[%s] 设置速度: %d%%\n", dev->name, value);break;case MOTOR_PARAM_DIRECTION:printf("[%s] 设置方向: %s\n", dev->name, value ? "正向" : "反向");break;default:printf("[%s] 未知参数: %d\n", dev->name, param);}
}// 电机资源销毁
static void motor_destroy(Peripheral* dev) {printf("[%s] 销毁资源 (地址: 0x%02X)\n", dev->name, dev->address);free(dev);
}// 创建电机设备
Peripheral* create_motor(int address) {Peripheral* motor = (Peripheral*)malloc(sizeof(Peripheral));if (!motor) return NULL;motor->name = "直流电机";motor->address = address;motor->status = 0; // 初始禁用状态motor->enable = motor_enable;motor->disable = motor_disable;motor->set_param = motor_set_param;motor->destroy = motor_destroy;return motor;
}// -------------------------- 具体产品实现(显示屏) --------------------------
// 显示屏特有参数定义
#define DISPLAY_PARAM_BRIGHTNESS 1 // 亮度参数
#define DISPLAY_PARAM_CONTRAST 2 // 对比度参数// 显示屏使能
static void display_enable(Peripheral* dev) {dev->status = 1;printf("[%s] 已使能 (地址: 0x%02X) - 屏幕点亮\n", dev->name, dev->address);
}// 显示屏禁用
static void display_disable(Peripheral* dev) {dev->status = 0;printf("[%s] 已禁用 (地址: 0x%02X) - 屏幕关闭\n", dev->name, dev->address);
}// 显示屏参数设置(亮度0-100,对比度0-100)
static void display_set_param(Peripheral* dev, int param, int value) {if (dev->status != 1) {printf("[%s] 未使能,无法设置参数\n", dev->name);return;}switch(param) {case DISPLAY_PARAM_BRIGHTNESS:printf("[%s] 设置亮度: %d%%\n", dev->name, value);break;case DISPLAY_PARAM_CONTRAST:printf("[%s] 设置对比度: %d%%\n", dev->name, value);break;default:printf("[%s] 未知参数: %d\n", dev->name, param);}
}// 显示屏资源销毁
static void display_destroy(Peripheral* dev) {printf("[%s] 销毁资源 (地址: 0x%02X)\n", dev->name, dev->address);free(dev);
}// 创建显示屏设备
Peripheral* create_display(int address) {Peripheral* display = (Peripheral*)malloc(sizeof(Peripheral));if (!display) return NULL;display->name = "OLED显示屏";display->address = address;display->status = 0; // 初始禁用状态display->enable = display_enable;display->disable = display_disable;display->set_param = display_set_param;display->destroy = display_destroy;return display;
}// -------------------------- 具体产品实现(继电器) --------------------------
// 继电器特有参数定义
#define RELAY_PARAM_DELAY 1 // 延迟参数(毫秒)// 继电器使能
static void relay_enable(Peripheral* dev) {dev->status = 1;printf("[%s] 已使能 (地址: 0x%02X) - 开关闭合\n", dev->name, dev->address);
}// 继电器禁用
static void relay_disable(Peripheral* dev) {dev->status = 0;printf("[%s] 已禁用 (地址: 0x%02X) - 开关断开\n", dev->name, dev->address);
}// 继电器参数设置(延迟时间)
static void relay_set_param(Peripheral* dev, int param, int value) {if (dev->status != 1) {printf("[%s] 未使能,无法设置参数\n", dev->name);return;}switch(param) {case RELAY_PARAM_DELAY:printf("[%s] 设置延迟: %d毫秒\n", dev->name, value);break;default:printf("[%s] 未知参数: %d\n", dev->name, param);}
}// 继电器资源销毁
static void relay_destroy(Peripheral* dev) {printf("[%s] 销毁资源 (地址: 0x%02X)\n", dev->name, dev->address);free(dev);
}// 创建继电器设备
Peripheral* create_relay(int address) {Peripheral* relay = (Peripheral*)malloc(sizeof(Peripheral));if (!relay) return NULL;relay->name = "电磁继电器";relay->address = address;relay->status = 0; // 初始禁用状态relay->enable = relay_enable;relay->disable = relay_disable;relay->set_param = relay_set_param;relay->destroy = relay_destroy;return relay;
}// -------------------------- 外设工厂定义 --------------------------
// 外设类型枚举
typedef enum {PERIPHERAL_MOTOR, // 电机PERIPHERAL_DISPLAY, // 显示屏PERIPHERAL_RELAY // 继电器
} PeripheralType;// 外设工厂:根据类型和地址创建对应外设
Peripheral* peripheral_factory_create(PeripheralType type, int address) {switch(type) {case PERIPHERAL_MOTOR:return create_motor(address);case PERIPHERAL_DISPLAY:return create_display(address);case PERIPHERAL_RELAY:return create_relay(address);default:printf("未知外设类型: %d\n", type);return NULL;}
}// -------------------------- 客户端示例(工业控制逻辑) --------------------------
// 外设控制通用函数(体现多态性)
void peripheral_operate(Peripheral* dev) {// 使能设备dev->enable(dev);// 设置设备特定参数(不同设备参数含义不同,但调用方式统一)if (strcmp(dev->name, "直流电机") == 0) {dev->set_param(dev, MOTOR_PARAM_SPEED, 70);dev->set_param(dev, MOTOR_PARAM_DIRECTION, 1);} else if (strcmp(dev->name, "OLED显示屏") == 0) {dev->set_param(dev, DISPLAY_PARAM_BRIGHTNESS, 80);dev->set_param(dev, DISPLAY_PARAM_CONTRAST, 50);} else if (strcmp(dev->name, "电磁继电器") == 0) {dev->set_param(dev, RELAY_PARAM_DELAY, 100);}// 禁用设备dev->disable(dev);
}int main() {// 通过工厂创建不同外设(地址用于区分硬件接口)Peripheral* motor = peripheral_factory_create(PERIPHERAL_MOTOR, 0x01);Peripheral* display = peripheral_factory_create(PERIPHERAL_DISPLAY, 0x02);Peripheral* relay = peripheral_factory_create(PERIPHERAL_RELAY, 0x03);if (!motor || !display || !relay) {printf("设备创建失败\n");return -1;}// 统一操作不同外设printf("=== 电机操作 ===\n");peripheral_operate(motor);printf("\n=== 显示屏操作 ===\n");peripheral_operate(display);printf("\n=== 继电器操作 ===\n");peripheral_operate(relay);// 销毁资源motor->destroy(motor);display->destroy(display);relay->destroy(relay);return 0;
}