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

文章目录

  • 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.mfbz.cn/a/156940.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

卡码网语言基础课 | 12. 位置互换

通过本次练习&#xff0c;将要学习到以下C知识点&#xff1a; 位置互换交换变量字符串 题目&#xff1a;给定一个长度为偶数位的字符串&#xff0c;请编程实现字符串的奇偶位互换。 奇偶位互换是指字符串的奇数位和偶数位相互交换位置 即&#xff1a;第一位和第二位交换&…

拷贝文件到u盘提示文件过大

在u盘空间足够的情况下&#xff0c;如果提示这个&#xff0c;可以手动修改一下ntfs格式 点击 WinR 键&#xff0c; 输入cmd回车 使用convert f:/fs:ntfs命令&#xff0c;此处的f为盘符&#xff0c;根据u盘所在的盘符设置。 如果u盘有隐藏的文件在自动运行&#xff0c;可能导致…

设计模式篇---装饰模式

文章目录 概念结构实例总结 概念 装饰模式&#xff1a;动态的给一个对象增加一些额外的职责。就扩展功能而言&#xff0c;装饰模式提供了 一种比使用子类更加灵活的替代方案。 装饰模式是一种对象结构型模式&#xff0c;它以对客户透明的方式动态地给一个对象附加上更多的责任…

2023-11-17 VsCode使用makefile进行多文件编译

点击 <C 语言编程核心突破> 快速C语言入门 VsCode使用makefile进行多文件编译 前言一、一个简单的多文件示例二、makefile基本语法三、VsCode使用makefile总结 前言 要解决问题: C或C可以多文件编译, 意味着需要进行代码组织, 为了方便多文件编译, gnu开发了make工具, …

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

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

双11背后的中国云厂商:新“标准化”,和调整后的新韧性

降价并不代表一味的压缩自身利润空间&#xff0c;云厂商已经开始向具有更高利润空间的PaaS、SaaS产品腾挪&#xff0c;核心产品在总包占比越来越高。 作者|斗斗 编辑|皮爷 出品|产业家 今年云厂商&#xff0c;全面拥抱双11。 作为中国最大的云计算服务提供商&#xff0…

释放搜索潜力:基于Milvus快速搭建语义检索系统(快速版),让信息尽在掌握

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…

完蛋! 我被MySQL索引失效包围了!

前言 一阵熟悉的起床闹钟响起&#xff0c;小菜同学醒来竟发现周围都是导致索引失效的原因&#xff1a;性感迷人的索引使用不当、可爱活泼的存储引擎无法识别索引列、刁蛮任性的优化器不选择索引... 知其然更要知其所以然&#xff0c;一起来看看索引为啥失效了吧~ 在阅读文本…

零基础安装分布式数据服务注册系统

一、先安装VM虚拟机&#xff0c;安装最新的ubuntu22系统&#xff0c; 先安装mysql&#xff0c; sudo apt install mysql-server sudo mysql_secure_installation 根据自己需求选择 密码安全级别时&#xff0c;选择n 删除匿名用户&#xff1f;&#xff08;按y|Y表示是&…

【加载自定义数据csv/image】HuggingFace的datasets库中load_dataset

1.加载自定义数据 load_dataset有以下参数&#xff0c;具体可参考 源码 def load_dataset(path: str,name: Optional[str] None,data_dir: Optional[str] None,data_files: Union[Dict, List] None,split: Optional[Union[str, Split]] None,cache_dir: Optional[str] No…

UE基础篇十一:Sequencer

导语: 视频文档在文末 知识点记录: 1、创建Sequence 2、动画可以设置权重值 作动画过渡 3、摄像机 可以设置追踪目标 调整一些摄像机参数等 4、在曲线编辑中编辑可以更详细调整路径 5、在一个序列中 添加添加另一个序列文件

git commit 后 发现提交信息写错了怎么办

解决方案&#xff1a; 可以使用 git commit --amend 命令。此命令将打开默认文本编辑器&#xff0c;允许你编辑最近的提交的提交信息。 以下是使用 git commit --amend 的步骤&#xff1a; 首先&#xff0c;在你的工作目录中进行所需的更改。运行 git add 命令将更改的文件添…

恒驰喜讯 | 荣获2023项目管理论坛“最佳集成服务伙伴”、“卓越合作伙伴项目经理”双奖

2023年11月7日~8日&#xff0c;以“价值交付共创未来”为主题的2023年项目管理论坛在深圳坂田成功举办。论坛上&#xff0c;来自海内外交付领域的200多名专家围绕项目管理实践、交付案例与项目优化等主题展开了深入交流&#xff0c;并就各区域项目管理案例做了经验分享&#xf…

ubuntu20.04.6安装Intel AX211网卡驱动

前言 环境&#xff1a; ThinkBook16 2023 款网卡Intel AX211 Wi-Fi6ubuntu版本20.04.6&#xff08;最后一位小数很重要&#xff09;系统内核 Linux wzy 5.15.0-67-generic #74~20.04.1-Ubuntu SMP Wed Feb 22 14:52:34 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux 方法&#x…

分布式事务 - seata安装

分布式事务 - seata 一、本地事务与分布式事务 1.1、本地事务 本地事务&#xff0c;也就是传统的单机事务。在传统数据库事务中&#xff0c;必须要满足四个原则&#xff08;ACID&#xff09;。 1.2、分布式事务 分布式事务&#xff0c;就是指不是在单个服务或单个数据库架构…

粉够荣获淘宝联盟理事会常务理事,共绘联盟生态新篇章

淘宝联盟区域理事会于2021年成立&#xff0c;首届成立成都、广州、武汉&#xff0c;服务近2000个领军淘宝客企业&#xff0c;作为区域生态与官方交流重要枢纽&#xff0c;理事会举办近百场交流分享会&#xff0c;带动淘客跨域跨业态交流成长。 2023年9月7日第二届淘宝联盟理事…

React实战项⽬开发完整流程含代码

React实战演练项⽬一需求分析及项目初始化 需求分析 刚学完React,开始找项目进行上手练习&#xff01; 页面组件拆分&#xff1a; 头部&#xff1a;导航tab、搜索框、登录注册 中间&#xff1a;分类导航、轮播图、新人福利、高单价产品导航 课程分类列表、底部内容、登陆提…

MinIO实现数据迁移(mc)

运行两个版本的minio version: 2.3 services: # 新版本 minio2023: image: minio/minio:RELEASE.2022-06-20T23-13-45Z.fips container_name: minio2023 restart: always environment: - MINIO_ACCESS_KEYminioadmin - MINIO_SECRET_KEYminioadmin - MINIO_ROOT_USERminioadm…
最新文章