1. Introduction
The core idea of the factory pattern is to:separate the creation and use of objects. Just like when you go to a store to buy something, you don’t need to worry about how the product is made; you just need to tell the clerk what you need.
Since this is a factory pattern, we definitely need to implement a factory class, which can produce a series of product objects. The factory needs to know the main characteristics of the products. For example, in a clothing factory, the clothing produced needs to determine style, color, size, material, etc., but each piece of clothing has its own unique style, color, size, material, etc.
Therefore, I need to determine the key components of the factory pattern: product interface, specific products, factory class, and registration mechanism. In C, function pointers in structures can simulate interfaces, and each specific product (such as different sensors) needs to implement these functions. The factory class is responsible for creating specific instances and requires a registration function to add new product types.
2. Advantages of the Factory Pattern
-
Module Decoupling: Separates object creation from usage
-
Easy Expansion: New device types can be added without modifying core logic
-
Simple Maintenance: Centralized device management reduces coupling
-
Code Reusability: Unified interface specification reduces duplicate code
3. Example
3.1 First, define the device interface
typedef struct { void (*Init)(void); float (*Read)(void); void (*Calibrate)(float offset);} SensorInterface;
Of course, if these products have some common characteristics, you can also add private variables.
3.2 Create the Factory
// Create factory classtypedef struct { SensorInterface* sensors[MAX_SENSORS]; uint8_t count;} SensorFactory;void SensorFactory_Register(SensorFactory* factory, SensorInterface* sensor) { if(factory->count < MAX_SENSORS) { factory->sensors[factory->count++] = sensor; }}SensorInterface* SensorFactory_Get(SensorFactory* factory, uint8_t index) { return (index < factory->count) ? factory->sensors[index] : NULL;}
3.3 Specific Implementation
// Implement specific devices// BMP180 pressure sensor driver:static void BMP180_Init() { /* Initialization code */ }static float BMP180_Read() { /* Read data */ }static void BMP180_Calibrate(float offset) { /* Calibration */ }const SensorInterface BMP180_Sensor = { .Init = BMP180_Init, .Read = BMP180_Read, .Calibrate = BMP180_Calibrate}; // DHT11 temperature and humidity sensor driver:static void DHT11_Init() { /* Initialization code */ }static float DHT11_Read() { /* Read data */ }static void DHT11_Calibrate(float offset) { /* Calibration */ }const SensorInterface DHT11_Sensor = { .Init = DHT11_Init, .Read = DHT11_Read, .Calibrate = DHT11_Calibrate};
3.4 Usage
int main(void) { SensorFactory factory = {0}; // Register available sensors SensorFactory_Register(&factory, &BMP180_Sensor); SensorFactory_Register(&factory, &DHT11_Sensor); // Dynamically select sensor BMP180_Sensor SensorInterface* currentSensor = SensorFactory_Create(&factory, 0); if(currentSensor) { currentSensor->Init(); float data = currentSensor->Read(); // Process data... } // Dynamically select sensor DHT11_Sensor currentSensor = SensorFactory_Create(&factory, 1); if(currentSensor) { currentSensor->Init(); float data = currentSensor->Read(); // Process data... }}