c生万物系列(职责链模式与if_else)

news2024/9/9 0:39:03

从处理器的角度来说,条件分支会导致指令流水线的中断,所以控制语句需要严格保存状态,因为处理器是很难直接进行逻辑判断的,有可能它会执行一段时间,发现出错后再返回,也有可能通过延时等手段完成控制流的正确性。所以笔者在想,使用过多的if _else,除了可读性差,是否还会对执行效率造成影响呢?

于是笔者决定采用职责链重构if控制语句,笔者猜想,如果采用设计模式既可以避免if分支,提高执行效率,同时可以让程序具备解耦合性和可维护性,是否是一种更优解呢?

为了验证笔者的猜想,更好的优化c语言程序,笔者使用职责链模式对一段if_else程序进行了重构。

程序的性能标准是执行时间,计算程序时间的程序来源于:C语言 计算程序运行时间(精确到毫秒/微秒)_c语言计算运行时间-CSDN博客

以下是笔者本人用c编写的责任链设计模式:

#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
#include<string.h>
#include <windows.h>


typedef int (*Handler)(int);

typedef struct task_node
{
	Handler handler;
	struct task_node* next;
}taskN;


int task1(int a) {
	if (a == 1) {
		//printf("a == 1"); printf会耗费大量时间,为了不影响测试,所以只留下判断语句
		return 0;
	}
	return -1;
}

int task2(int a) {
	if (a == 2) {
		
		return 0;
	}
	return -1;
}

int task3(int a) {
	if (a == 3) {
		
		return 0;
	}
	return -1;
}


int task4(int a) {
	if (a == 4) {
		
		return 0;
	}
	return -1;
}


int task5(int a) {
	if (a == 5) {
		
		return 0;
	}
	return -1;
}


int task6(int a) {
	if (a == 6) {
		
		return 0;
	}
	return -1;
}


int task7(int a) {
	if (a == 7) {
		
		return 0;
	}
	return -1;
}


int task8(int a) {
	if (a == 8) {
		
		return 0;
	}
	return -1;
}


int task9(int a) {
	if (a == 9) {
		
		return 0;
	}
	return -1;
}


int task10(int a) {
	if (a == 10) {
		
		return 0;
	}
	return -1;
}


int task11(int a) {
	if (a == 11) {
		
		return 0;
	}
	return -1;
}


int task12(int a) {
	if (a == 12) {
		return 0;
	}
	return -1;
}

taskN* initi() {
   
	taskN* tas1 = malloc(sizeof(taskN));
	taskN* tas2 = malloc(sizeof(taskN));
	taskN* tas3 = malloc(sizeof(taskN));
	taskN* tas4 = malloc(sizeof(taskN));
	taskN* tas5 = malloc(sizeof(taskN));
	taskN* tas6 = malloc(sizeof(taskN));
	taskN* tas7 = malloc(sizeof(taskN));
	taskN* tas8 = malloc(sizeof(taskN));
	taskN* tas9 = malloc(sizeof(taskN));
	taskN* tas10 = malloc(sizeof(taskN));
	taskN* tas11= malloc(sizeof(taskN));
	taskN* tas12= malloc(sizeof(taskN));

	tas1->handler = task1;
	tas2->handler = task2;
	tas3->handler = task3;
	tas4->handler = task4;
	tas5->handler = task5;
	tas6->handler = task6;
	tas7->handler = task7;
	tas8->handler = task8;
	tas9->handler = task9;
	tas10->handler = task10;
	tas11->handler = task11;
	tas12->handler = task12;

	tas1->next = tas2;
	tas2->next = tas3;
	tas3->next = tas4;
	tas4->next = tas5;
	tas5->next = tas6;
	tas6->next = tas7;
	tas7->next = tas8;
	tas8->next = tas9;
	tas9->next = tas10;
	tas10->next = tas11;
	tas11->next = tas12;
	
	return tas1;


}



void process(taskN* bol, int a) {
	int i = bol->handler(a);
	while (i != 0)
	{
		i = bol->handler(a);
		bol = bol->next;
		
	}
}


void main() {
	double run_time;
	LARGE_INTEGER time_start;	//开始时间
	LARGE_INTEGER time_over;	//结束时间
	double dqFreq;		//计时器频率
	LARGE_INTEGER f;	//计时器频率
	QueryPerformanceFrequency(&f);
	dqFreq = (double)f.QuadPart;
	QueryPerformanceCounter(&time_start);
	taskN* bol = initi();
	
	int a = 12;

	
	for (int i = 0; i <= 50000000; i++)
	{
	/*
	if (a == 1) {

	}
	else if (a == 2) {

	}
	else if (a == 3) {

	}
	else if (a == 4) {

	}
	else if (a == 5) {

	}
	else if (a == 6) {

	}
	else if (a == 7) {

	}
	else if (a == 8) {

	}
	else if (a == 9) {

	}
	else if (a == 10) {

	}
	else if (a == 11) {

	}
	else if (a == 12) {

	}
	else {

	}
	
	*/

	
	/*
	process(bol, a);

	*/


		switch (a) {
		case 1:
			break;
		case 2:

			break;
		case 3:

			break;
		case 4:

			break;
		case 5:

			break;
		case 6:

			break;
		case 7:

			break;
		case 8:

			break;
		case 9:

			break;
		case 10:
			break;
		case 11:

			break;
		case 12:

			break;
		default:

			break;
		}
	}
	
	QueryPerformanceCounter(&time_over);	//计时结束
	run_time = 1000000 * (time_over.QuadPart - time_start.QuadPart) / dqFreq;
	//乘以1000000把单位由秒化为微秒,精度为1000 000/(cpu主频)微秒
	printf("\nrun_time:%fus\n", run_time);
     /*为了偷懒,程序就懒得free了*/

	
}

使用if_else时:

a=1,第一个循环执行:

a=12,最后一个循环执行:

两者时间基本没区别,在循环语句中

笔者还测试了只有if( a== 1)这一个判断语句下的性能:

可以看出基本没什么区别。

使用case时:

a=12时如下,与a=1时的结果几乎没有区别:

switch语句除了比较简洁一点,执行速度完全没法比。

 使用责任链时:

任务优先级在责任链上过高(a=1):

 任务优先级在责任链过低(a=12):

可以看出,职责链的速度非常慢,特别是任务优先级低时,执行速度几乎是if_else的150倍。

综上得出,if_else的执行速度是最快的,如果判断的时间复杂度过大,而且判断语句的数量较少,使用if_else,性能可能会更好。

但是,上述的前提是建立在判断语句的数量较少的情况下。

现在让我们考虑这样一种情况:不是判断a从1到12,而是从a到10000呢?程序等价于下图:

再附加一个条件,大多数情况下,a的值都是1。

虽然if_else的耗时比较短,但是在大量的循环下,耗时也不容小觑。因为a大多数情况是1,其他的判断分支只有小概率发生,此时我们使用责任链就可以完美跳过这些语句的判断:

(程序用for循环表示中间的分支,写得不准确,理解意思就好)

当然,读者可能认为if else if在这里也可以跳过中间的语句,也能实现优先级,但是如果改成这样呢:

这种情况下,if else if只能执行其中一个,显然不行,使用大量的if,就变成了上面的情况,我们不得不将原先的代码大量删除并重写,这十分让人难受。这样一对比,对于部分实现的if分支,使用责任链的优点有什么呢?如下图:

在责任链任务里进行改动,可以选择责任链终止的位置,跳过后面的任务,当然,通过goto等跳转指令也是可以实现的,但是if语句很难做到这样灵活,对于复杂的业务场景,很难在原先的基础上进行拓展,责任链的解耦合性和可拓展性是非常好的优点。

考虑复杂的业务场景,责任链明显优于传统的if_else。

尽管如此,if_else还是十分友好的,特别是在mcu等产品的开发中,使用设计模式的资源花费简直是奢求,毕竟设计模式是针对高级语言的,大多数情况下if_else往往是最优解。不过,笔者认为大量使用if_else的前提是项目不需要长期维护,一般情况下还是要多使用设计模式,例如在linux内核中就有源码使用了责任链模式,这是从性能,解耦合性和可读性等多方面考虑,值得开发者学习。如果是小型项目,对维护没有要求,而且控制语句的数量较少,为了性能和简便性可以考虑直接使用if_else分支。但是如果大型项目中含有大量if分支,可以考虑使用设计模式重构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1958494.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

skynet 实操篇

文章目录 概述demo启动文件skynet_start配置文件main.luastart函数thread_workerskynet_context_message_dispatchskynet_mq_popdispatch_message 小结 概述 上一篇写完skynet入门篇&#xff0c;这一篇写点实操性质的。 demo 对于一个开源框架&#xff0c;大部分都有他们自己…

《Linux运维总结:基于x86_64架构CPU使用docker-compose一键离线部署zookeeper 3.8.4容器版分布式集群》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;《Linux运维篇&#xff1a;Linux系统运维指南》 一、部署背景 由于业务系统的特殊性&#xff0c;我们需要面对不同的客户部署业务系统&#xff0…

C++客户端Qt开发——界面优化(美化登录界面)

美化登录界面 在.ui中拖入一个QFream&#xff0c;顶层窗口的QWidget无法设置背景图片&#xff0c;套上一层QFrame将背景图片设置到QFrame上即可 用布局管理器管理元素&#xff1a;用户名LineEdit&#xff0c;密码LineEdit&#xff0c;记住密码ComboBox&#xff0c;登录Button…

ubuntu2204安装elasticsearch7.17.22

下载安装 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.22-amd64.deb wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.22-amd64.deb.sha512 shasum -a 512 -c elasticsearch-7.17.22-amd64.deb.sha512 su…

web、http协议、apache服务、nginx服务

web基本概念和常识 概念 web&#xff1a;为用户提供的一种在互联网上浏览信息的服务&#xff0c;是动态的、可交互的、跨平台的和图形化的&#xff1b; 为用户提供各种互联网服务&#xff0c;这些服务包括浏览服务以及各种交互式服务&#xff0c;包括聊天、购物等&#xff1…

windows下,pyrouge安装教程

1.安装perl 1.1 在命令行&#xff0c;检查perl是否安装 perl-v 1.2 安装perl 下载地址 Strawberry Perl for Windows - Releases 1&#xff09;下载msi版本 2&#xff09;双击安装包&#xff0c;傻瓜式安装&#xff0c;一路next&#xff0c;&#xff08;可修改安装路径&am…

Matlab编程资源库(16)数值微分

一、数值差分与差商 在Matlab中&#xff0c;数值差分与差商是数值分析中常用的概念&#xff0c;尤其在求解微分方程、插值、逼近等领域有广泛应用。下面简要介绍这两个概念及其在Matlab中的实现。 数值差分 数值差分是微分运算的离散化形式&#xff0c;用于近似求解导数。给定…

宠物浮毛空气净化器真的有用吗?性价比高的浮毛空气净化器推荐

作为一位5年资深铲屎官&#xff0c;随着养猫的家庭数量不断增加&#xff0c;轻松撸猫虽然很快乐。然而&#xff0c;宠物的存在也可能引发一些问题&#xff0c;比如宠物的体味和脱落的毛发&#xff0c;这些都可能成为影响家庭健康的隐患。特别是宠物排泄物的气味&#xff0c;如果…

C++11中的右值引用以及移动构造等

目录 一、右值引用 1.左值引用和右值引用 2.左值引用与右值引用比较 3.右值引用使用场景和意义 1️⃣ 传返回值 2️⃣ STL中的应用 4.完美转发 模板中的&& 万能引用&#xff08;引用折叠&#xff09; 二、 新的类功能 1.默认成员函数 2.类成员变量初始化 3.…

【找到字符串中所有字母异位词】python刷题记录

R2-滑动窗口篇 滑动窗口哈希表 和之前那道一样 http://t.csdnimg.cn/dpIbt class Solution:def findAnagrams(self, s: str, p: str) -> List[int]:#返回字典记录了每个字符出现的次数counter1collections.Counter(p)#滑动窗口记录counter2即可ret[]num2len(s)num1len(p…

VIM基础配置

1. CTAGS配置 下载 上传虚拟机&#xff0c;解压&#xff0c;进入目录 tar -xzvf ctags-5.8.tar.gz cd ctags-5.8/编译 ./configure sudo make sudo make install查看是否安装成功 ctags --version打印如下 2. 使用Vundle 下载 git clone https://github.com/VundleVim/Vund…

如何将WordPress文章中的外链图片批量导入到本地

在使用采集软件进行内容创作时&#xff0c;很多文章中的图片都是远程链接&#xff0c;这不仅会导致前端加载速度慢&#xff0c;还会在微信小程序和抖音小程序中添加各种域名&#xff0c;造成管理上的麻烦。特别是遇到没有备案的外链&#xff0c;更是让人头疼。因此&#xff0c;…

2024下《系统架构设计师》案例简答题,刷这些就够了!

2024年软考下半年已经越来越近了&#xff0c;不知道今年备考架构的同学们准备得怎么样了呢&#xff1f; 简答题一直是架构拿分的重点区域&#xff0c;对于许多考生来说&#xff0c;也往往是最具挑战性的部分。今天我就把那些重要的案例简答题类型整理汇总给大家&#xff0c;希望…

C++选择题带答案

1&#xff0e;下列关于定义一个指向double型变量的指针&#xff0c;正确的是&#xff08; B &#xff09;。 A&#xff0e;int a(5)&#xff1b;double *pda&#xff1b; B&#xff0e;double d(2.5)&#xff0c;*pd&d&#xff1b; C&#xff0e;dou…

uniapp时间戳转时间

时间戳转时间 utils页面 function timestampToTime(time) { const date new Date(time); const year date.getFullYear(); const month String(date.getMonth() 1).padStart(2, 0); // 月份从0开始&#xff0c;所以要加1&#xff0c;并补齐0 const day String(date…

系统架构师考点--系统架构设计(下)

大家好。今天总结一下系统架构设计的最后一部分知识点。 一、软件系统的质量属性 软件系统的质量属性 软件系统的质量属性可分为开发期质量属性和运行期质量属性2个部分。 1、开发期质量属性主要指在软件开发阶段所关注的质量属性&#xff0c;主要包含6个方面&#xff1a; …

联想电脑怎么重装系统_联想电脑U盘重装win10详细图文教程

联想电脑怎么重装系统&#xff1f;在当今科技发展迅猛的时代&#xff0c;联想电脑已经成为了人们生活中不可或缺的一部分。然而&#xff0c;随着时间的推移&#xff0c;我们可能会遇到一些问题&#xff0c;例如系统崩溃或者需要更换操作系统。这时&#xff0c;使用U盘来重新安装…

57页PPT智慧水利数字孪生综合解决方案

实现“全局一盘棋”的智慧水利综合管理&#xff0c;关键在于整合水利大数据、数字孪生与人工智能技术&#xff0c;通过“一图、一库、一平台”的构建&#xff0c;为水利工作提供全面、科学、智能的管理和决策支持。以下是对这一目标的详细解读和实现路径&#xff1a; 知识星球…

C/C++进阶 (8)哈希表(STL)

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a;C 本文着重于模拟实现哈希表&#xff0c;并非是哈希表的使用。 实现的哈希表的底层用的是线性探测法&#xff0c;并非是哈希桶。 目录 一、标准库中的哈希表 1、unordered_map 2、unordered_set 二、模…

【计算机毕设论文】基于SpringBoot线上学习平台的设计与实现

&#x1f497;博主介绍&#xff1a;✌全平台粉丝5W,高级大厂开发程序员&#x1f603;&#xff0c;博客之星、掘金/知乎/华为云/阿里云等平台优质作者。 【源码获取】关注并且私信我 感兴趣的可以先收藏起来&#xff0c;同学门有不懂的毕设选题&#xff0c;项目以及论文编写等相…