C语言实现设计模式的往期回顾:
3. 用C语言实现原型模式!
6. 用C语言实现适配器模式!
👀
一、概述
1.策略模式简介
策略模式 (Strategy)也叫是行为模式之一,它对一系列的算法加以封装,为所有算法定义一个抽象的算法接口,并通过继承该抽象算法接口对所有的算法加以封装和实现,具体的算法选择交由客户端决定(策略)。Strategy 模式主要用来平滑地处理算法的切换。
2.策略模式特点
准备一组算法,并将每一个算法封装起来,使得它们可以互换。
3.UML 类图
类图描述: 定义一个抽象接口类 Strategy,具体类 A、B、C 通过继承实现接口中的定义。Context 环境类,内部包含 Strategy 定义的对象,调用 Strategy 类的 operation(),通过多态的发生实现不同的操作。
👀
二、设计思路
本片以笔记本电脑实现联网功能为例,有 3 种联网方式,通过网线联网、WiFi 联网、USB 连接手机提供网络。为了举例,假设每一种联网方式对于笔记本电脑来说都是一种操作算法,我们把这三种算法抽象一个公共类 Strategy,如果 Computer(电脑)联网访问 Strategy 提高的统一抽象接口,通过发生“多态”实现不同的联网功能。
具体的策略设计模式的类图如下:
👀
三、实现
1.策略模式抽象接口结构体的定义
typedef struct Istrategy
{
int (*operate)(void* obj);
void (*free)(void* obj);
}Istrategy;
2.具体策略类实现, 使用网线连接网络结构体的实现
typedef struct net_cable_strategy
{
int (*operate)(void* obj); //“继承”抽象接口函数
void (*free)(void* obj); //“继承”抽象接口函数
float rate; //自身特有属性
float len; //自身特有属性
}net_cable_strategy;
//使用网线联网函数实现
static int net_cable_operate(void *obj)
{
if(!obj) return -1;
net_cable_strategy* nobj = (net_cable_strategy*)obj;
printf("使用【网线】给电脑连接网络...\n");
printf("网络速率: %.2fM/s\n", nobj->rate);
printf("网线长度: %.0fm\n", nobj->len);
}
//释放结构体内存
static void net_cable_free(void *obj)
{
if(!obj) return;
free(obj);
obj = NULL;
}
//“构造函数” 创建一个对象
net_cable_strategy* construct_net_cable(void)
{
net_cable_strategy* obj = (net_cable_strategy*)malloc(sizeof(net_cable_strategy));
if(!obj) return NULL;
obj->operate = net_cable_operate;
obj->free = net_cable_free;
obj->rate = 53.34;
obj->len = 100;
return obj;
}
3.具体实现类,通过连接 WIFI 提供网络
typedef struct net_wifi_strategy
{
int (*operate)(void* obj); //“继承”抽象接口函数
void (*free)(void* obj); //“继承”抽象接口函数
float rate; //自身特有属性
char *describe;//自身特有属性
}net_wifi_strategy;
//使用WIFI联网函数实现
static int net_wifi_operate(void *obj)
{
if(!obj) return -1;
net_wifi_strategy* nobj = (net_wifi_strategy*)obj;
printf("使用【WIFI】给电脑连接网络...\n");
printf("网络速率: %.2fM/s\n", nobj->rate);
printf("描述:%s\n", nobj->describe);
}
//释放内存
static void net_wifi_free(void *obj)
{
if(!obj) return;
net_wifi_strategy* nobj = (net_wifi_strategy*)obj;
if(nobj->describe) free(nobj->describe);
nobj->describe = NULL;
free(obj);
obj = NULL;
}
//“构造函数” 创建一个对象
net_wifi_strategy* construct_net_wifi(void)
{
net_wifi_strategy* obj = (net_wifi_strategy*)malloc(sizeof(net_wifi_strategy));
if(!obj) return NULL;
obj->operate = net_wifi_operate;
obj->free = net_wifi_free;
obj->rate = 23.34;
obj->describe = (char*)malloc(64);
sprintf(obj->describe, "WIFI4, 802.11n, 频段 2.4GHz, 理论最大速率 600Mbps");
return obj;
}
4.使用 USB 连接手机通过网络定义与实现和上面的类似,限于篇幅,不再赘述。
👀
四、功能测试
下面是 main 函数,测试策略模式功能。通过“构造函数”创建对象的联网对象,实现不同的联网功能,而调用接口和流程保持不变。
int main(void)
{
printf("Test Strategy Mode...\n");
Istrategy *net = NULL;
computer* com_obj = NULL;
net = (Istrategy *)construct_net_cable();
com_obj = construct_computer(net);
com_obj->work(com_obj);
com_obj->free(com_obj);
printf("-----------split-----------\n\n");
net = (Istrategy *)construct_net_wifi();
com_obj = construct_computer(net);
com_obj->work(com_obj);
com_obj->free(com_obj);
printf("-----------split-----------\n\n");
net = (Istrategy *)construct_net_usb();
com_obj = construct_computer(net);
com_obj->work(com_obj);
com_obj->free(com_obj);
printf("-----------split-----------\n\n");
return 0;
}
测试结果:
👀
五、策略模式特点总结
策略模式的优点:
A. 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句。
B. 策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
C. 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
D. 策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
E. 策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。
缺点:
A. 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。 B. 策略模式造成很多的策略类。
虽然C语言是面向过程的编程语言,但是我们在设计程序的时候,可以考虑用面向对象的方式去设计,这样提高我们程序的“高内聚、低耦合”特性,便于维护。
👀
六、总结
想要完整设计模式代码的小伙伴:在微信公众号【Linux编程用C】后台回复 designer 即可获取,不断更新中!
这个是交流群,欢迎大家扫描加入,一起分享学习!
(注:如果二维码过期了请添加小C微信号:LinuxCodeUseC 拉入群聊)
PS:若大家想看C语言版本的其他设计模式,
请大家 点赞! 转发!关注吧!~~