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.mzph.cn/news/145474.shtml

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

相关文章

Python武器库开发-flask篇之路由和视图函数(二十二)

flask篇之路由和视图函数(二十二) 通过创建路由并关联函数&#xff0c;实现一个基本的网页&#xff1a; #!/usr/bin/env python3 from flask import Flask# 用当前脚本名称实例化Flask对象&#xff0c;方便flask从该脚本文件中获取需要的内容 app Flask(__name__)#程序实例需…

软文推广中媒体矩阵的优势在哪儿

咱们日常生活中是不是经常听到一句俗语&#xff0c;不要把鸡蛋放在同一个篮子里&#xff0c;其实在广告界这句话也同样适用&#xff0c;媒介矩阵是指企业在策划广告活动时&#xff0c;有目的、有计划的利用多种媒体进行广告传播&#xff0c;触达目标用户。今天媒介盒子就来和大…

pipeline jenkins流水线

Pipeline 是 Jenkins 中一种灵活且强大的工作流机制&#xff0c;它允许您以代码的形式来定义和管理持续集成和持续交付的流程。 Pipeline 的作用主要体现在以下几个方面&#xff1a; 可编排的构建流程&#xff1a;使用 Pipeline&#xff0c;您可以将一个或多个阶段&#xff08…

微信抽奖活动怎么做

微信抽奖活动&#xff1a;打破传统&#xff0c;创新互动&#xff0c;带给你超乎想象的惊喜体验&#xff01; 随着互联网的飞速发展&#xff0c;人们越来越热衷于参与各种线上活动。而微信&#xff0c;作为中国最大的社交平台之一&#xff0c;自然成为了各种活动的聚集地。今天…

Android设计模式--状态模式

真知即所以为行&#xff0c;不行不足谓之知 一&#xff0c;定义 当一个对象的内在状态改变时&#xff0c;允许改变其行为&#xff0c;这个对象看起来像是改变了其类。 这么说可能很难理解&#xff0c;通俗来讲就是当一个对象它有多种状态的时候&#xff0c;把每一种状态的行为…

大数据毕业设计选题推荐-机房信息大数据平台-Hadoop-Spark-Hive

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

本地MQTT协议消息服务远程连接教程介绍

Mosquitto是一个开源的消息代理&#xff0c;它实现了MQTT协议版本3.1和3.1.1。它可以在不同的平台上运行&#xff0c;包括Windows、Linux、macOS等。mosquitto可以用于物联网、传感器、移动应用程序等场景&#xff0c;提供了一种轻量级的、可靠的、基于发布/订阅模式的消息传递…

高标准农田数字孪生

高标准农田是指通过土地整治、土壤改良、水利设施、农电配套、机械化作业等措施&#xff0c;提升农田质量和生产能力&#xff0c;达到田块平整、集中连片、设施完善、节水高效、宜机作业、土壤肥沃、生态友好、抗灾能力强、与现代农业生产和经营方式相适应的旱涝保收、稳产高产…

【docker启动的Jenkins时,遇到时区问题处理】

1、查看容器中的时区 [rootlocalhost jenkins]# docker exec -it jenkins cat /etc/timezone Etc/UTC而本地使用的是Asia/shanghai [rootlocalhost jenkins]# timedatectl | grep Time zoneTime zone: n/a (CST, 0800)###查看 [rootlocalhost jenkins]# cd /usr/share/zoneinf…

【Coppeliasim仿真】 坐标系间平滑插补

在仿真环境中控制两个参考框架&#xff08;ReferenceFrame1和ReferenceFrame2&#xff09;之间进行平滑的插值运动。在两个参考框架之间插值运动的过程中&#xff0c;使用了两种不同的方法&#xff0c;通过设置useMethodNb来选择使用的方法。 方法1使用了旋转轴和角度的计算&a…

Windows 小狼毫 如何在安装后指定用户配置文件文件夹

Windows 小狼毫 如何在安装后指定用户配置文件文件夹 打开小狼毫的安装目录&#xff0c;双击目录中的 WeaselSetup.exe 就会弹出截图中的那个窗口&#xff0c;然后指定你的用户文件夹目录就可以了

云ES高级监控告警

一、高级监控告警配置 1.1 操作入口 1.2 配置告警模块 1.2.1 新建联系人 添加联系人后,需要进行激活 1.2.2 新建联系人组 1.2.3 创建报警组 1.2.4 新建报警规则

鸿蒙4.0真机调试踩坑

传言鸿蒙next版本将不再兼容Android&#xff0c;所以领导安排做下鸿蒙开发的调研工作。 鸿蒙开发指南其实已经非常的友好了。但是鸿蒙开发本身还是有些坑要踩&#xff0c;这篇文章主要讲了鸿蒙真机调试问题。 目前手上的真机为华为 nova6&#xff0c;处理器为麒麟990.鸿蒙系统…

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

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

Github小彩蛋显示自己的README,git 个人首页的 README,readme基本语法

先上效果&#x1f447; 代码在下面&#xff0c;流程我放最下面了&#xff0c;思路就是创建一个和自己同名的仓库&#xff0c;要公开&#xff0c;创建的时候会提示小彩蛋你的reademe会展示在你的首页&#xff0c;或许你在这个readme里面的修改都会在你的主页上看到了&#x1f44…

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;深入探讨提升抖店服务分的有效方法。 一、了解抖店服务分的评估标准 …

010.cat、find

1、用cat进行拼接 cat命令能够显示或拼接文件内容&#xff0c;不过它的能力远不止如此。比如说&#xff0c;cat能够将标准输入数据与文件数据组合在一起。通常的做法是将stdin重定向到一个文件&#xff0c;然后再合并两个文件。而cat命令一次就能搞定这些操作。 用cat读取文件…

人工智能基础_机器学习039_sigmoid函数_逻辑回归_逻辑斯蒂回归_分类神器_代码实现逻辑回归图---人工智能工作笔记0079

逻辑斯蒂回归(Logistic Regression)是一种常用的分类算法,其基本思想是通过拟合一个逻辑斯蒂函数来预测样本所属的类别。它广泛应用于各个领域,如医学、金融、市场营销等,具有较好的解释性和可解释性。在逻辑斯蒂回归中,我们通常使用的是二分类问题,即样本只属于两个类别…

线下保薪班开启

大家都知道我们有线上班&#xff0c;对于想技能提升的同学来说&#xff0c;线上足以满足技能提升需求&#xff0c;对于想转行找工作&#xff0c;或者学生想就业的同学来说&#xff0c;线上却并不是一个好的选择&#xff0c;担心的可能有:担心自身基础较弱怕学不懂&#xff0c;担…