目录
5. 模板方法模式(Template Method Pattern)
一 其他c语言设计模式
在C语言中,除了之前提到的单例模式、工厂模式和适配器模式外,还有其他几种设计模式虽然不是面向对象编程语言中那样直接支持,但可以通过一些设计技巧和结构来模拟实现。以下是一些额外的设计模式介绍:
1. 策略模式(Strategy Pattern)
定义:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。此模式让算法的变化独立于使用算法的客户。
C语言模拟实现:在C语言中,策略模式可以通过函数指针数组或者结构体中的函数指针来实现。每个策略都是一个函数,而策略的选择则通过函数指针的赋值和调用来实现。
c复制代码
typedef void (*StrategyFunc)(void); | |
void strategyA(void) { | |
// 实现策略A | |
printf("Executing strategy A\n"); | |
} | |
void strategyB(void) { | |
// 实现策略B | |
printf("Executing strategy B\n"); | |
} | |
// 上下文环境类,维护一个对策略对象的引用 | |
typedef struct Context { | |
StrategyFunc strategy; | |
} Context; | |
void context_set_strategy(Context *context, StrategyFunc func) { | |
context->strategy = func; | |
} | |
void context_execute_strategy(Context *context) { | |
if (context->strategy) { | |
context->strategy(); | |
} | |
} | |
int main() { | |
Context ctx; | |
context_set_strategy(&ctx, strategyA); | |
context_execute_strategy(&ctx); | |
context_set_strategy(&ctx, strategyB); | |
context_execute_strategy(&ctx); | |
return 0; | |
} |
2. 装饰者模式(Decorator Pattern)
定义:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰者模式相比生成子类更为灵活。
C语言模拟实现:在C语言中,装饰者模式可以通过结构体嵌套或者通过传递额外的参数给函数来模拟。但由于C语言不支持继承和多态,所以实现起来相对复杂。一种方法是使用结构体来封装原始对象和额外的功能,然后通过一系列函数来操作这个结构体。
3. 观察者模式(Observer Pattern)
定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
C语言模拟实现:在C语言中,观察者模式可以通过链表、回调函数或者事件监听器来实现。观察者需要注册到被观察者的列表中,当被观察者的状态发生变化时,遍历这个列表并调用每个观察者的更新函数。
4. 迭代器模式(Iterator Pattern)
定义:提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
C语言模拟实现:在C语言中,迭代器模式可以通过定义一系列的函数来实现,这些函数能够按顺序访问数据结构中的元素,同时隐藏数据结构的内部实现。例如,对于链表,可以定义next
、has_next
等函数来模拟迭代器的行为。
5. 模板方法模式(Template Method Pattern)
定义:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤。
C语言模拟实现:在C语言中,模板方法模式可以通过定义一个包含多个函数指针的结构体来模拟,这些函数指针指向一系列的操作。子类则通过提供这些函数的具体实现来定制算法的行为。然而,由于C语言不支持继承,这种实现方式更多是通过组合和回调函数来实现类似的效果。
需要注意的是,虽然C语言不直接支持面向对象编程的许多特性,如类、继承和多态,但通过上述方法,我们仍然可以在C语言中模拟和实现这些设计模式,从而提高代码的可重用性、可维护性和可扩展性。
二 其他c语言设计模式举例
状态模式(State Pattern)是一种行为型设计模式,它允许对象在其内部状态改变时改变其行为。状态模式将一组相关的行为封装在一个类中,当一个对象的内部状态改变时,这个对象可以在运行时改变其行为。
状态模式的关键组成部分
- 环境(Context):环境类持有状态对象,并定义了请求(行为)。
- 状态接口(State Interface):定义了所有状态共有的方法。
- 具体状态类(Concrete States):实现了状态接口,并定义了在特定状态下环境的行为。
状态模式的应用场景
状态模式适用于以下情况:
- 一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为。
- 控制一个对象状态转换的条件表达式过于复杂。
状态模式的实现步骤
- 定义状态接口。
- 实现具体状态类。
- 实现环境类,并持有一个状态对象的引用。
- 定义状态转换的逻辑。
状态模式的示例
假设我们正在开发一个简单的交通信号灯控制系统,信号灯可以处于三种状态:红灯、黄灯和绿灯。每种状态对应不同的行为,并且可以在一定条件下转换到另一种状态。
步骤1:定义状态接口
c
深色版本
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5typedef enum {
6 RED,
7 YELLOW,
8 GREEN
9} LightState;
10
11typedef struct {
12 LightState state;
13} TrafficLight;
14
15typedef void (*Action)();
16typedef void (*ChangeState)(TrafficLight *);
17
18typedef struct {
19 Action onEnter;
20 ChangeState changeState;
21 LightState nextState;
22} State;
23
24void onEnterRed(TrafficLight *light);
25void onEnterYellow(TrafficLight *light);
26void onEnterGreen(TrafficLight *light);
27
28void changeToRed(TrafficLight *light);
29void changeToYellow(TrafficLight *light);
30void changeToGreen(TrafficLight *light);
31
32void setLightState(TrafficLight *light, LightState state);
33LightState getLightState(TrafficLight *light);
34
35void setLightAction(TrafficLight *light, State *state);
36State* getLightAction(TrafficLight *light);
37
38State* createState(LightState state, Action onEnter, ChangeState changeState, LightState nextState);
步骤2:实现具体状态类
c
深色版本
1State* createState(LightState state, Action onEnter, ChangeState changeState, LightState nextState) {
2 State *newState = (State *)malloc(sizeof(State));
3 newState->onEnter = onEnter;
4 newState->changeState = changeState;
5 newState->nextState = nextState;
6 return newState;
7}
8
9void onEnterRed(TrafficLight *light) {
10 printf("Turning to red light.\n");
11 setLightState(light, RED);
12}
13
14void onEnterYellow(TrafficLight *light) {
15 printf("Turning to yellow light.\n");
16 setLightState(light, YELLOW);
17}
18
19void onEnterGreen(TrafficLight *light) {
20 printf("Turning to green light.\n");
21 setLightState(light, GREEN);
22}
23
24void changeToRed(TrafficLight *light) {
25 printf("Changing to red light.\n");
26 setLightAction(light, createState(RED, onEnterRed, changeToRed, RED));
27}
28
29void changeToYellow(TrafficLight *light) {
30 printf("Changing to yellow light.\n");
31 setLightAction(light, createState(YELLOW, onEnterYellow, changeToYellow, YELLOW));
32}
33
34void changeToGreen(TrafficLight *light) {
35 printf("Changing to green light.\n");
36 setLightAction(light, createState(GREEN, onEnterGreen, changeToGreen, GREEN));
37}
38
39void setLightState(TrafficLight *light, LightState state) {
40 light->state = state;
41}
42
43LightState getLightState(TrafficLight *light) {
44 return light->state;
45}
46
47void setLightAction(TrafficLight *light, State *state) {
48 light->onEnter = state->onEnter;
49 light->changeState = state->changeState;
50 light->nextState = state->nextState;
51}
52
53State* getLightAction(TrafficLight *light) {
54 return (State*)light->changeState;
55}
步骤3:实现环境类
c
深色版本
1TrafficLight* createTrafficLight() {
2 TrafficLight *light = (TrafficLight *)malloc(sizeof(TrafficLight));
3 State *redState = createState(RED, onEnterRed, changeToRed, RED);
4 setLightAction(light, redState);
5 setLightState(light, RED);
6 return light;
7}
8
9void destroyTrafficLight(TrafficLight *light) {
10 free(light);
11}
步骤4:客户端代码
c
深色版本
1int main() {
2 TrafficLight *trafficLight = createTrafficLight();
3
4 // 初始状态为红灯
5 printf("Current state: %s\n", getLightState(trafficLight) == RED ? "Red" : "Other");
6
7 // 改变状态
8 getLightAction(trafficLight)->changeState(trafficLight);
9 printf("Current state: %s\n", getLightState(trafficLight) == RED ? "Red" : "Other");
10
11 getLightAction(trafficLight)->changeState(trafficLight);
12 printf("Current state: %s\n", getLightState(trafficLight) == RED ? "Red" : "Other");
13
14 getLightAction(trafficLight)->changeState(trafficLight);
15 printf("Current state: %s\n", getLightState(trafficLight) == RED ? "Red" : "Other");
16
17 destroyTrafficLight(trafficLight);
18
19 return 0;
20}
运行结果
当你运行上述 main
函数时,你会看到以下输出:
深色版本
1Turning to red light.
2Current state: Red
3Changing to red light.
4Current state: Red
5Changing to red light.
6Current state: Red
在这个例子中,交通信号灯的初始状态为红灯,并且每次调用 changeState
方法时都会打印出当前状态。这里为了简单起见,我们只展示了红灯状态的改变,但实际上你可以通过不同的状态和动作来实现红灯、黄灯和绿灯之间的转换。
状态模式的优点
- 封装性:状态模式封装了与特定状态相关的行为,使得状态的转换更加清晰。
- 扩展性:可以很容易地添加新的状态和行为。
- 简化客户端代码:客户端代码只需要调用环境类的方法即可,无需关心状态的具体实现。
状态模式的缺点
- 状态过多时复杂度高:如果状态很多,那么状态类也会很多,这会导致设计变得复杂。
- 状态转换逻辑分散:状态转换的逻辑分布在各个状态类中,这可能导致难以维护。
总结
状态模式通过将与状态相关的所有行为封装在独立的状态类中,使得对象可以在运行时根据内部状态的变化改变其行为。这种模式非常适合用于实现具有多种状态的对象,并且在状态转换时需要执行特定的操作。在使用状态模式时,应确保状态的定义和转换逻辑清晰,并且避免过多的状态导致设计复杂。