职责链模式的应用之模拟JavaWeb的双向过滤器(混合了组合模式)
程序员文章站
2022-05-26 08:50:06
...
思考职责链模式
①职责链的本质:分离职责,动态组合。分离职责是前提,动态组合才是职责链模式的精华所在,因为这意味着可以很方便地修改和添加新的处理对象,从而让系统更加灵活和具有更好的扩展性。
②职责链的动机:在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时需要有接受者,如果显式指定,将必不可少地带来请求发送者与接受者之间的紧耦合。而职责链模式可以将这两者解耦,使得发送者不必知道具体的接受者(处理者)
2. 功能链(如过滤器)
(1)概念:实际开发中,经常将一个请求在职责链中传递,每个职责对象负责处理请求的某一方面的功能,处理完后不是停止,而是继续向下传递请求,当请求通过很多职责对象处理后,功能也就完成了,把这样的职责链称为功能链。
(2)应用举例
①实际开发中,在业务处理之前,通常需要进行权限检查、数据校验、逻辑检查等,然后才开始真正的业务逻辑。可以把这些功能分散到一个功能链中。
②过滤器:每个过滤器负责自己的处理,然后转交给下一个过滤器,直到把所有的过滤器都走完(如权限检查、字符转换等)。
【编程实验】字符过滤器(模拟JavaWeb的双向过滤器,变式的职责链模式)
//声明文件
//*********************************************************************************************
//行为型模式:职责链模式
//场景:字符过滤(模拟JavaWeb的双向过滤器)
//当客户端发送给服务器时,request字符串被各个过滤器按顺序处理,
//而返回的response是逆着过滤器被调用顺序被处理的。(可参考下面的技巧)
//思路细节技巧:
//(1)Filter的doFilter方法改为doFilter(Request*,Resopnse*,FilterChain*),有
//FilterChain指针,为利用FilterChain调用下一个Filter做准备
//(2)FilterChain继承Filter,这样,FilterChain既是FilterChain又是Filter,那么
//FilterChain就可以调用Filter的方法doFilter(Request*,Resopnse*,FilterChain*)
//(3)FilterChain的doFilter(Request*,Resopnse*,FilterChain*)中,有index标记了执
//行到第几个Filter,当所有Filter执行完后request处理后,就会return,以倒序继续执
//行response处理
#include <iostream>
#include <string>
#include <vector>
using namespace std;
//*************************************************字符串替换函数*********************************
void Replace(std::basic_string<char>& s, const std::basic_string<char>& src, const std::basic_string<char>& dest);
//***************************辅助类*****************
//请求类
class CRequest{
private:
string strContent;//请求的内容
public:
CRequest(string content);
void SetContent(string content);
string& GetContent();
};
//响应类
class CResponse{
private:
string strContent;//响应的内容
public:
CResponse(string content);
void SetContent(string content);
string& GetContent();
};
//***************************抽象职责类*************
//Filter(抽象过滤器)
class CFilterChain;
class CFilter{
public:
virtual ~CFilter();
virtual bool IsChain();
virtual vector<CFilter*>* GetFilters();
virtual void DoFilter(CRequest* req, CResponse* res, CFilterChain* chain) = 0;
};
//FilterChain(过滤器链)
//注意,FilterChain继承自Filter,是为了这个链可以像其他过滤器(如HTMLFilter)一样地被加入到其他链中
//从而,可以将两条FilterChain连接成一条。
class CFilterChain : public CFilter{
private:
vector<CFilter*> vFilter;
int iIdx;
public:
CFilterChain();
~CFilterChain();
bool IsChain();
vector<CFilter*>* GetFilters();
CFilterChain& AddFilter(CFilter* filter);
//将链本身作为一个过滤器,也实现了doFilter功能,但这里只是简单地调用链中各个
//过滤器并记录下一个过滤器的索引
void DoFilter(CRequest* req, CResponse* res, CFilterChain* chain);
};
//HtmlFilter
class CHtmlFilter : public CFilter{
public:
~CHtmlFilter();
//当客户端发送给服务器时,request字符串被各个过滤器后按顺序处理,
//而返回的response逆着过滤器被调用顺序被处理。(可参考下面的技巧)
void DoFilter(CRequest* req, CResponse* res, CFilterChain* chain);
};
//SensitiveFilter(敏感关键字过滤器)
class CSensitiveFilter : public CFilter{
public:
~CSensitiveFilter();
void DoFilter(CRequest* req, CResponse* res, CFilterChain* chain);
};
//FaceFilter(表情过滤器)
class CFaceFilter : public CFilter{
public:
~CFaceFilter();
void DoFilter(CRequest* req, CResponse* res, CFilterChain* chain);
};
void DelFilter(CFilter* pRoot);
//实现文件
//*************************************************字符串替换函数*********************************
void Replace(std::basic_string<char>& s, const std::basic_string<char>& src, const std::basic_string<char>& dest)
{
std::basic_string<char>::size_type pos = 0;
while (true)
{
pos = s.find(src, pos);
if (std::basic_string<char>::npos == pos)
break;
s.replace(pos, src.size(), dest);
pos += src.size();
}
}
//****************************************************************************************
//***************************辅助类*****************
//请求类
CRequest::CRequest(string content){strContent = content;}
void CRequest::SetContent(string content){strContent = content;}
string& CRequest::GetContent(){return strContent;}
//响应类
CResponse::CResponse(string content){strContent = content;}
void CResponse::SetContent(string content){strContent = content;}
string& CResponse::GetContent(){return strContent;}
//***************************抽象职责类*************
//职责链
//Filter(抽象过滤器)
CFilter::~CFilter(){}
bool CFilter::IsChain(){return false;}
vector<CFilter*>* CFilter::GetFilters(){return NULL;}
//FilterChain(过滤器链)
//注意,FilterChain继承自Filter,是为了这个链可以像其他过滤器(如HTMLFilter)一样地被加入到其他链中
//从而,可以将两条FilterChain连接成一条。
CFilterChain::CFilterChain(){iIdx = 0;}
CFilterChain::~CFilterChain(){ cout << "~CFilterChain" << endl;}
bool CFilterChain::IsChain(){return true;}
vector<CFilter*>* CFilterChain::GetFilters(){return &vFilter;}
CFilterChain& CFilterChain::AddFilter(CFilter* filter){vFilter.push_back(filter); return *this;}
//将链本身作为一个过滤器,也实现了doFilter功能,但这里只是简单地调用链中各个
//过滤器并记录下一个过滤器的索引
void CFilterChain::DoFilter(CRequest* req, CResponse* res, CFilterChain* chain){
if(iIdx == vFilter.size()) return;
CFilter* pFilter = vFilter[iIdx++];
pFilter->DoFilter(req, res, chain);
}
//HtmlFilter
//当客户端发送给服务器时,request字符串被各个过滤器后按顺序处理,
//而返回的response逆着过滤器被调用顺序被处理。(可参考下面的技巧)
CHtmlFilter::~CHtmlFilter(){cout << "~CHtmlFilter" << endl;}
void CHtmlFilter::DoFilter(CRequest* req, CResponse* res, CFilterChain* chain){
//1、处理html标签
Replace(req->GetContent(), "<", "[");
Replace(req->GetContent(), ">", "]");
req->GetContent() += "-->HtmlFilter";
//2、调用下一个过滤器(注意里面可能会递归)
chain->DoFilter(req, res, chain);
//3、在前2步之后,再处理response,可以达到栈式(逆序)处理response字符串-->技巧!
res->GetContent() += "-->HtmlFilter";
}
//SensitiveFilter(敏感关键字过滤器)
CSensitiveFilter::~CSensitiveFilter(){cout << "~CSensitiveFilter" << endl;}
void CSensitiveFilter::DoFilter(CRequest* req, CResponse* res, CFilterChain* chain){
//1、处理敏感关键词
Replace(req->GetContent(), "敏感", "");
Replace(req->GetContent(), "被就业", "就业");
req->GetContent() += "-->SensitiveFilter";
//2、调用下一个过滤器(注意里面可能会递归)
chain->DoFilter(req, res, chain);
//3、在前2步之后,再处理response,可以达到栈式(逆序)处理response字符串-->技巧!
res->GetContent() += "-->SensitiveFilter";
}
//FaceFilter(表情过滤器)
CFaceFilter::~CFaceFilter(){cout << "~CFaceFilter" << endl;}
void CFaceFilter::DoFilter(CRequest* req, CResponse* res, CFilterChain* chain){
//1、处理敏感关键词
Replace(req->GetContent(), ":)", "^V^");
req->GetContent() += "-->FaceFilter";
//2、调用下一个过滤器(注意里面可能会递归)
chain->DoFilter(req, res, chain);
//3、在前2步之后,再处理response,可以达到栈式(逆序)处理response字符串-->技巧!
res->GetContent() += "-->FaceFilter";
}
void DelFilter(CFilter* pRoot){
vector<CFilter*>* pFilters = pRoot->GetFilters();
if(pFilters != NULL){
for(vector<CFilter*>::iterator it = pFilters->begin(); it != pFilters->end(); it++){
CFilter* pFilter = (*it);
if(pFilter->IsChain()) DelFilter(pFilter);
else delete pFilter;
}
}
delete pRoot;
}
//测试客户端
void main()
{
string strReq = "大家好:),<script>,敏感,被就业,网络授课没感觉,因为看不见大家伙儿";
CRequest oRequest("Request : " + strReq);
CResponse oResponse("Response : ");
//创建3个过滤器
CFilter* pHtmlFilter = new CHtmlFilter();//HTML标签过滤
CFilter* pSensitiveFilter = new CSensitiveFilter();//敏感关键词过滤
CFilter* pFaceFilter = new CFaceFilter(); //表情过滤
CFilterChain* pMainFilterChain = new CFilterChain();//第1条过滤链(有两个过滤器)
pMainFilterChain->AddFilter(pHtmlFilter);
pMainFilterChain->AddFilter(pSensitiveFilter);
CFilterChain* pSubFilterChain = new CFilterChain(); //第2条过滤链(只有一个过滤器)
pSubFilterChain->AddFilter(pFaceFilter);
//交两条过滤链合成一条过滤链(共有3个过滤器)
pMainFilterChain->AddFilter(pSubFilterChain);
//开始过滤
pMainFilterChain->DoFilter(&oRequest, &oResponse, pMainFilterChain);
cout << oRequest.GetContent() << endl;
cout << oResponse.GetContent() << endl;
DelFilter(pMainFilterChain);
}
上一篇: PHP 的变量
下一篇: PHP实现微信发红包程序