C/C++轻量级并发TCP服务器框架Zinx-框架开发003:转大写字母输出+责任链模式+代码重构思路及实现

news2024/11/26 7:28:46

文章目录

  • 1 添加转大写字母输出功能
  • 2 责任链模式
    • 2.1 责任链的设计
    • 2.2 责任链的实现
    • 2.3 责任链的测试
  • 3 代码重构
    • 3.1 类图设计
    • 3.2 重构设计 - 头文件
    • 3.3 重构实现

1 添加转大写字母输出功能

在这里插入图片描述
在这里插入图片描述功能流程:

  • stdin通道类中包含一个功能处理类对象
  • 功能处理类中包含一个stdout类对象
  • 数据被读取到stdin通道,stdin通道将其交给功能处理类对象,该对象判断数据特点后转大写或直接交个stdout类对象进行输出
class process_func {
public:
	void DataProc(string &_input)
	{
		string output = _input;
		transform(output.begin(), output.end(), output.begin(),::toupper);
		poOut->DataPush(output);
	}
} *poProcess = new process_func();

/

class stdin_channel :public Ichannel {
public:

	// 通过 Ichannel 继承
	virtual bool ReadFd(std::string & _input) override
	{
		cin >> _input;
		return true;
	}

	virtual bool WriteFd(std::string & _output) override
	{
		return false;
	}

	virtual int GetFd() override
	{
		return 0;
	}

	virtual bool DataProcess(std::string & _data) override
	{
		poProcess->DataProc(_data);
		return true;
	}
};

2 责任链模式

在这里插入图片描述
通道类和功能处理类的对象都是整个流程中的环节,将这些环节连起来则形成责任链。

处理者类设计:

  • 提供handle函数作为链式处理的入口
  • handle内部执行当前环节的处理,并执行下一阶段的处理函数,直到没有下一环节
  • 提供internalhandle纯虚函数用来执行本环节处理
  • 提供getnext纯虚函数用来获取下一环节

消息类设计:

  • 只提供虚析构函数,用户可自行扩展

在这里插入图片描述在这里插入图片描述

2.1 责任链的设计

/*责任链设计*/
class IZinxMsg {
public:
	IZinxMsg() {}
	virtual ~IZinxMsg() {}
};



class AZinxHandler {
public:
	AZinxHandler() {}
	virtual ~AZinxHandler() {}
	void Handle(IZinxMsg &_oInput);
protected:
	virtual IZinxMsg *InternelHandle(IZinxMsg &_oInput) = 0;
	virtual AZinxHandler *GetNextHandler(IZinxMsg &_oNextMsg) = 0;
};

2.2 责任链的实现

/*责任链实现*/
void AZinxHandler::Handle(IZinxMsg & _oInput)
{
	IZinxMsg *poNextMsg = NULL;
	AZinxHandler *poNextHandler = NULL;

	poNextMsg = InternelHandle(_oInput);
	if (NULL != poNextMsg)
	{
        /*下一个环节处理*/
		poNextHandler = GetNextHandler(*poNextMsg);
        
        /*有下一个环节才处理*/
		if (NULL != poNextHandler)
		{
			poNextHandler->Handle(*poNextMsg);
		}

		delete poNextMsg;
	}

	return;
}

2.3 责任链的测试

/*责任链测试:将一串字符串交给处理者1进行首字母大写并输出,然后转交给处理者2进行字符统计并输出*/
class str_msg :public IZinxMsg {
public:
	str_msg(string &_content):content(_content) {}
	string content;
};

class h2_Count :public AZinxHandler {
	// 通过 AZinxHandler 继承
	virtual IZinxMsg * InternelHandle(IZinxMsg & _oInput) override
	{
		auto input = dynamic_cast<str_msg&>(_oInput);
		cout << "处理者2处理开始" << endl;
		cout << input.content.size() << endl;
		cout << "处理者2处理结束" << endl;
		return NULL;
	}
	virtual AZinxHandler * GetNextHandler(IZinxMsg & _oNextMsg) override
	{
		return nullptr;
	}
} h2;

class h1_UpperFirst :public AZinxHandler {
	// 通过 AZinxHandler 继承
	virtual IZinxMsg * InternelHandle(IZinxMsg & _oInput) override
	{
		auto input = dynamic_cast<str_msg&>(_oInput);
		cout << "处理者1处理开始" << endl;
		str_msg *pret = new str_msg(input.content);
		auto head = pret->content.begin();
		transform(head, head+1, head, ::toupper);
		cout << pret->content << endl;
		cout << "处理者1处理结束" << endl;
		return pret;
	}
	virtual AZinxHandler * GetNextHandler(IZinxMsg & _oNextMsg) override
	{
		return &h2;
	}
} h1;

int main()
{
	string input = "hello";
	str_msg input_msg(input);
	h1.Handle(input_msg);
}

3 代码重构

3.1 类图设计

在这里插入图片描述

3.2 重构设计 - 头文件

重构通道类和功能处理类(继承handler类):

  • 通道类的data_process函数不要了,通过重写internelhandle实现
  • 功能处理类的dataproc函数不要了,通过重写internelhandle实现
  • stdin类通过重写getnext方法返回功能处理对象
  • 功能处理类重写getnext方法返回stdout对象

重构kernel类:

  • epoll中不再执行channel类的方法,替换成handler类的handle方法
  • kernel类判断当前epoll的触发方向并将其封装为消息类对象传递给通道类
  • kernel增加函数用来处理程序向外发送数据(取代直接调用通道类的sendout函数)

创建消息类(继承message类)

  • 创建IO方向类用来让epoll给channel对象传递当前ready的IO方向
  • 创建byte消息类用来让channel对象给功能处理对象传递待处理字符串
  • 逐级继承保证消息内容丰富性
/*重构类---设计*/

#define GET_REF2DATA(type, ref, orig)  type * pref = dynamic_cast<type *>(&orig); if (nullptr == pref) {return nullptr;} type &ref = dynamic_cast<type&>(orig)

class IZinxMsg {
public:
	IZinxMsg() {}
	virtual ~IZinxMsg() {}
};

class SysIOReadyMsg :public IZinxMsg {
public:
	enum IO_DIC {
		IN, OUT
	} m_emIoDic;

	SysIOReadyMsg(IO_DIC _dic) :m_emIoDic(_dic) {}
};

class BytesMsg :public SysIOReadyMsg {
public:
	BytesMsg(SysIOReadyMsg &_base) :SysIOReadyMsg(_base.m_emIoDic) {}
	std::string szData;
};

//

class AZinxHandler {
public:
	AZinxHandler() {}
	virtual ~AZinxHandler() {}
	void Handle(IZinxMsg &_oInput);
protected:
	virtual IZinxMsg *InternelHandle(IZinxMsg &_oInput) = 0;
	virtual AZinxHandler *GetNextHandler(IZinxMsg &_oNextMsg) = 0;
};


class Ichannel:public AZinxHandler {
public:
	virtual bool ReadFd(std::string &_input) = 0;
	virtual bool WriteFd(std::string &_output) = 0;
	virtual int GetFd() = 0;
	void DataSendOut();
	void DataPush(std::string &_data);
	std::list<std::string> m_write_buffer;

	virtual IZinxMsg * InternelHandle(IZinxMsg & _oInput) override;
};


class ZinxKernel {
	static void Zinx_SendOut(std::string &_output, Ichannel &_oChannel);
};

3.3 重构实现

/*重构实现*/
void ZinxKernel::Zinx_Run()
{
	int iEpollRet = -1;

	for(;;)
	{
		struct epoll_event atmpEvent[100];
		iEpollRet = epoll_wait(GetInstance()->iEpollFd, atmpEvent, 100, -1);
		if (-1 == iEpollRet)
		{
			if (EINTR == errno)
			{
				continue;
			}
			else
			{
				break;
			}
		}
		for (int i = 0; i < iEpollRet; i++)
		{
			Ichannel *poChannel = static_cast<Ichannel *>(atmpEvent[i].data.ptr);
			if (0 != (EPOLLIN & atmpEvent[i].events))
			{
				string input;
				SysIOReadyMsg IoStat = SysIOReadyMsg(SysIOReadyMsg::IN);
				poChannel->Handle(IoStat);
			}
			if (0 != (EPOLLOUT & atmpEvent[i].events))
			{
				poChannel->DataSendOut();
				if (poChannel->m_write_buffer.empty())
				{
					Zinx_ClearChannelOut(*poChannel);
				}
			}
		}
	}
}


void ZinxKernel::Zinx_SendOut(std::string & _output, Ichannel & _oChannel)
{
	SysIOReadyMsg iodic = SysIOReadyMsg(SysIOReadyMsg::OUT);
	BytesMsg oBytes = BytesMsg(iodic);
	oBytes.szData = _output;
	_oChannel.Handle(oBytes);
}


IZinxMsg * Ichannel::InternelHandle(IZinxMsg & _oInput)
{
	IZinxMsg *poRet = NULL;
	GET_REF2DATA(SysIOReadyMsg, oIoStat, _oInput);
	if (oIoStat.m_emIoDic == SysIOReadyMsg::IN)
	{
		BytesMsg *poBytes = new BytesMsg(oIoStat);
		if (true == ReadFd(poBytes->szData))
		{
			poRet = poBytes;
		}
		else
		{
			delete poBytes;
		}
	}
	else if (oIoStat.m_emIoDic == SysIOReadyMsg::OUT)
	{
		GET_REF2DATA(BytesMsg, oBytes, _oInput);
		if (true == m_write_buffer.empty())
		{
			ZinxKernel::Zinx_SetChannelOut(*this);
		}
		m_write_buffer.push_back(oBytes.szData);
	}

	return poRet;
}
/*重构后测试*/
#include "Zinx.h"
#include <algorithm>
using namespace std;

class stdout_channel :public Ichannel {
public:
	virtual bool ReadFd(std::string & _input) override
	{
		return false;
	}
	virtual bool WriteFd(std::string & _output) override
	{
		cout << _output << endl;
		return true;
	}
	virtual int GetFd() override
	{
		return 1;
	}
	virtual AZinxHandler * GetNextHandler(IZinxMsg & _oNextMsg) override
	{
		return nullptr;
	}

} *poOut = new stdout_channel();

class process_func :public AZinxHandler{
public:
	void DataProc(string &_input)
	{
		string output = _input;
		transform(output.begin(), output.end(), output.begin(),::toupper);
		poOut->DataPush(output);
	}
	virtual IZinxMsg * InternelHandle(IZinxMsg & _oInput) override
	{
		GET_REF2DATA(BytesMsg, input, _oInput);
		string output = input.szData;
		transform(output.begin(), output.end(), output.begin(), ::toupper);
		ZinxKernel::Zinx_SendOut(output, *poOut);
		return NULL;
	}
	virtual AZinxHandler * GetNextHandler(IZinxMsg & _oNextMsg) override
	{
		return nullptr;
	}
} *poProcess = new process_func();

class stdin_channel :public Ichannel {
public:
	virtual bool ReadFd(std::string & _input) override
	{
		cin >> _input;
		return true;
	}

	virtual bool WriteFd(std::string & _output) override
	{
		return false;
	}

	virtual int GetFd() override
	{
		return 0;
	}
	virtual AZinxHandler * GetNextHandler(IZinxMsg & _oNextMsg) override
	{
		return poProcess;
	}

};

int main()
{
	ZinxKernel::ZinxKernelInit();
	ZinxKernel::Zinx_Add_Channel(*(new stdin_channel()));
	ZinxKernel::Zinx_Add_Channel(*poOut);
	ZinxKernel::Zinx_Run();
	ZinxKernel::ZinxKernelFini();
}

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

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

相关文章

【嵌入式】如何改造STLINK,使其在下载程序时无需外接3.3V电源

文章目录 1. 问题2. 原因及解决方法3. 开始改造4. 参考资料 1. 问题 在使用这种大号的 STLINK 给开发板下载程序时&#xff0c;都需要对开发板进行供电&#xff0c;有些麻烦&#xff0c;但是使用 J-Link 的时候就不需要外接电源&#xff0c;那有没有什么办法可以将 STLINK 改造…

谁家分析数据还要开发啊,不都一键得报表吗?

点击导入数据&#xff0c;再回来BI系统已经把近百张数据分析报表放在眼前了&#xff0c;每月都要计算分析的指标有了&#xff0c;领导要的数据分析有了&#xff0c;自己要的业绩分析也有了&#xff0c;甚至自己没想到的一些分析主题&#xff0c;它也贴心地做好了。有这样一套BI…

13.Oracle通过JDBC连接Java

Oracle通过JDBC连接Java 一、什么是JDBC二、Oracle通过JDBC连接Java1、导入jar包1.1 下载jar包1.2 将jar包导入到java项目中1.3编译jar包 2、连接数据库2.1 编写jdbc工具类2.2 对数据进行基本操作 一、什么是JDBC JDBC&#xff08;Java Database Connectivity&#xff09;是Jav…

mysql查询json字符串内容

参考文章&#xff1a;mysql json 基础查询_mysql json查询-CSDN博客 mysql查询json字符串内容 &#xff08;多层数组嵌套&#xff09; select id,nameJSON_EXTRACT(JSON_UNQUOTE(JSON_EXTRACT(JSON_UNQUOTE(config_json), $.baseInfo)), $.template_list[*].sms_content) s…

在微信上怎么做抽奖活动

微信抽奖活动&#xff1a;让你轻松吸引粉丝&#xff0c;打造火爆互动场景&#xff01; 随着微信的普及&#xff0c;越来越多的人开始利用微信平台进行营销和推广。而微信抽奖活动作为一种有效的营销手段&#xff0c;能够迅速吸引用户的关注和参与&#xff0c;提高品牌曝光度和…

文件包含_具体场景、zip、php相关问题

具体场景—上传可控的文件 具体场景—远程文件包含 具体场景—伪协议

使用键盘管理器更改键盘快捷键,让键盘真正迎合你的使用习惯

如果默认快捷键不适合你&#xff0c;你肯定会想知道如何在Windows 11中更改键盘快捷键。 也许你已经习惯了macOS键盘&#xff0c;或者像我一样在Windows和Mac之间切换工作/游戏——如果是这样的话&#xff0c;重新配置默认的Windows快捷方式&#xff0c;使其与Mac上的快捷方式…

畜牧业可视化畜牧业数字孪生

"畜牧业是我国重要的农业产业之一&#xff0c;对于国民经济的发展和人民群众的生活具有重要的意义。智慧畜牧作为现代畜牧业的发展方向之一&#xff0c;将信息技术和现代管理相结合&#xff0c;提高养殖效率和品质&#xff0c;为行业的可持续发展注入新的动力。智慧畜牧是…

产品经理的能力模型是什么?

一个产品的成功需要团队成员利用自己的技能共同合作完成。作为团队的核心和产品的主导者&#xff0c;产品经理需要具备一定的能力模型&#xff0c;以更好地完成工作。下面从五个方面进行解答。 首先&#xff0c;产品经理需要具备需求分析的能力。需求是用户在特定场景下产生的欲…

go语言学习之旅之Go语言数据类型

学无止境&#xff0c;今天学习Go 语言数据类型 Go&#xff08;或Golang&#xff09;是一种静态类型语言&#xff0c;这意味着变量的数据类型必须显式声明&#xff0c;并且在运行时不能更改。以下是Go中的一些基本数据类型&#xff1a; 这里仅介绍最常用的类型 数值类型: int: …

计算机领域十大天神

✍️作者简介&#xff1a;沫小北/码农小北&#xff08;专注于Android、Web、TCP/IP等技术方向&#xff09; &#x1f433;博客主页&#xff1a;沫小北/码农小北 开源中国、稀土掘金、51cto博客、博客园、知乎、简书、慕课网、CSDN &#x1f514;如果文章对您有一定的帮助请&…

Redis篇---第四篇

系列文章目录 文章目录 系列文章目录前言一、说一下 Redis 有什么优点和缺点二、Redis 缓存刷新策略有哪些?三、Redis 持久化方式有哪些?以及有什么区别?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章…

OpenLayer系列——【一】初识OpenLayer与OpenLayer视图操作

初识OpenLayer 1、初始化地图渲染 安装openlayer依赖 npm i ol首先准备一个容器用来渲染地图 <div id"map" ref"map" style"width: 100%; height: 100%" />导入依赖初始化地图 import ol/ol.css; import OSM from ol/source/OSM.js; …

浅谈智能安全配电装置应用在银行配电系统中

【摘要】银行是国家重点安全保护部分&#xff0c;关系到社会资金的稳定&#xff0c;也是消防重点单位。消防安全是银行工作的重要组成部分。在银行配电系统中应用智能安全配电装置&#xff0c;可以提高银行的智能控制水平&#xff0c;有效预防电气火灾。 【关键词】银行&#…

敲敲云与简道云流程设计引擎对比:选择更适合您的产品

在当今数字化时代&#xff0c;流程管理和自动化变得越来越重要。作为APaaS服务的两个知名产品&#xff0c;敲敲云和简道云都提供了流程设计引擎&#xff0c;帮助企业实现高效的流程管理。然而&#xff0c;在比较两者之后&#xff0c;您可能会发现敲敲云在多个方面具有优势&…

2023年05月 Scratch(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

一、单选题(共25题,每题2分,共50分) 第1题 看图找规律,请问下图红框中是?( ) A: B: C: D: 答案:D 第2题 用一根绳子绕树一圈余30厘米,如果绕树二圈则差40厘米,请问绳子长多少厘米?( )<

经典文献阅读之--Surround-View Survey(自动驾驶中基于环视视觉的3D检测综述)

0. 简介 对于基于环视视觉的3D检测而言&#xff0c;目前已经有很多文章了。因为基于视觉的3D检测任务是自动驾驶系统感知的基本任务&#xff0c;然而&#xff0c;使用单目相机的2D传感器输入数据来实现相当好的3D BEV&#xff08;鸟瞰图&#xff09;性能不是一项容易的任务。这…

素质教育正式提出30周年 提高实际应用能力成为教育新选择

至2023年“素质教育”已正式提出30周年。在实施期间,素质教育取得了显著成就:不仅提高了学生的综合素质和竞争力,培养了学生的创新能力、实践能力等,同时也改变了应试导向和知识灌输的教育模式,建立了以人为本、以学为主的教育理念。 教育观念发生扭转,教育目标也随之改变。学…

jenkins-2.426.1-1.1.noarch.rpm 的公钥没有安装

执行命令 yum install jenkins 报错 jenkins-2.426.1-1.1.noarch.rpm 的公钥没有安装 下载的软件包保存在缓存中&#xff0c;直到下次成功执行事务。 您可以通过执行 yum clean packages 删除软件包缓存。 错误&#xff1a;GPG 检查失败 解决办法&#xff1a; 1、安装新的公…

OpenShift 4 - 就地调整 Pod 资源使用量

《OpenShift / RHEL / DevSecOps 汇总目录》 说明&#xff1a;本文已经在 OpenShift 4.14 的环境中验证 文章目录 为什么需要就地调整 Pod 资源启动 InPlacePodVerticalScaling 特性实现就地调整 Pod 资源参考 为什么需要就地调整 Pod 资源 以往在 Kubernetes 中调整 Pod 的 …