1.简介
工厂方法模式是一种创建型设计模式,它定义了一个接口用于创建对象,但允许子类决定实例化哪一个类。这种模式让一个类的实例化延迟到其子类,从而实现了解耦和扩展性。
在 C 语言中,由于没有类的概念,工厂方法模式通常通过函数指针和结构体来实现。我们将通过一个简单的例子来说明这一点。
2.通俗讲解
假设我们需要一个程序,它可以计算各种形状的面积,如圆形、矩形和三角形。我们可以使用工厂方法模式来实现这一点。
3.实战
3.1.代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 抽象产品 Shape
typedef struct {
double (*area)();
} Shape;
// 具体产品 Circle
typedef struct {
double radius;
double area() {
return 3.14159 * radius * radius;
}
} Circle;
// 具体产品 Rectangle
typedef struct {
double width;
double height;
double area() {
return width * height;
}
} Rectangle;
// 具体产品 Triangle
typedef struct {
double base;
double height;
double area() {
return 0.5 * base * height;
}
} Triangle;
// 抽象工厂
typedef Shape *(*CreateShapeFunc)(void);
// 具体工厂 CreateCircle
Shape *createCircle(double radius) {
Circle *circle = (Circle *)malloc(sizeof(Circle));
circle->radius = radius;
circle->area = circle->area; // 设置成员函数
return (Shape *)circle;
}
// 具体工厂 CreateRectangle
Shape *createRectangle(double width, double height) {
Rectangle *rectangle = (Rectangle *)malloc(sizeof(Rectangle));
rectangle->width = width;
rectangle->height = height;
rectangle->area = rectangle->area; // 设置成员函数
return (Shape *)rectangle;
}
// 具体工厂 CreateTriangle
Shape *createTriangle(double base, double height) {
Triangle *triangle = (Triangle *)malloc(sizeof(Triangle));
triangle->base = base;
triangle->height = height;
triangle->area = triangle->area; // 设置成员函数
return (Shape *)triangle;
}
// 工厂方法 CreateFactory
CreateShapeFunc createFactory(const char *type) {
if (strcmp(type, "circle") == 0) {
return createCircle;
} else if (strcmp(type, "rectangle") == 0) {
return createRectangle;
} else if (strcmp(type, "triangle") == 0) {
return createTriangle;
}
return NULL;
}
// 主函数
int main() {
const char *shapeType = "circle"; // 可以替换为其他形状
CreateShapeFunc factory = createFactory(shapeType);
Shape *shape = NULL;
if (factory != NULL) {
if (strcmp(shapeType, "circle") == 0) {
shape = factory(5.0); // 圆形半径
} else if (strcmp(shapeType, "rectangle") == 0) {
shape = factory(4.0, 6.0); // 矩形宽高
} else if (strcmp(shapeType, "triangle") == 0) {
shape = factory(3.0, 4.0); // 三角形底高
}
if (shape != NULL) {
double area = ((Shape *)shape)->area();
printf("The area of the %s is %.2f\n", shapeType, area);
free(shape); // 释放内存
}
}
return 0;
}
3.2.代码解析
- 抽象产品 (Shape): 定义了一个结构体,包含一个计算面积的函数指针。
- 具体产品 (Circle, Rectangle, Triangle): 每个具体产品都有自己的属性和计算面积的方法。
- 抽象工厂 (CreateShapeFunc): 定义了一个返回具体形状创建函数的类型。
- 具体工厂 (createCircle, createRectangle, createTriangle): 每个具体工厂负责创建特定形状的对象。
- 工厂方法 (createFactory): 根据传入的形状类型返回相应的具体工厂函数。
- 客户端代码 (main): 使用工厂方法创建形状,并调用面积计算方法。
这种设计的好处是,我们可以很容易地添加新的图形类型,例如三角形,只需添加新的结构体和工厂方法,而不需要修改客户端代码。这就实现了代码的解耦和可扩展性。
3.3.代码运行
当你运行上面的代码时,会得到如下输出:
The area of the circle is 78.54
3.4.结果分析
在这个例子中,我们首先定义了一个抽象产品 Shape 和三个具体产品 Circle, Rectangle, 和 Triangle。每个具体产品都实现了 area() 方法以计算面积。然后,我们定义了一个抽象工厂 createShape 和三个具体工厂 createCircle, createRectangle, 和 createTriangle,它们分别负责创建具体的形状。
在主函数 main 中,我们通过 createFactory 函数选择具体工厂,进而创建所需的形状并计算其面积。这种方式的好处是,如果未来需要添加更多的形状类型,只需添加新的具体产品和具体工厂即可,而无需修改现有的代码。
4.总结
工厂方法模式在 C 语言中的实现尽管比在面向对象语言中要复杂一些,但它依然能够有效地帮助我们实现对象的创建和管理。通过使用函数指针和结构体,我们能够在 C 语言中实现这一经典的设计模式。