文章目录
- 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();
}