欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

职责链模式的应用之模拟JavaWeb的双向过滤器(混合了组合模式)

程序员文章站 2022-05-26 08:50:06
...
思考职责链模式

  ①职责链的本质分离职责,动态组合。分离职责是前提,动态组合才是职责链模式的精华所在,因为这意味着可以很方便地修改和添加新的处理对象,从而让系统更加灵活和具有更好的扩展性。

  ②职责链的动机:在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时需要有接受者,如果显式指定,将必不可少地带来请求发送者与接受者之间的紧耦合。而职责链模式可以将这两者解耦,使得发送者不必知道具体的接受者(处理者)

2. 功能链(如过滤器)

(1)概念:实际开发中,经常将一个请求在职责链中传递,每个职责对象负责处理请求的某一方面的功能,处理完后不是停止,而是继续向下传递请求,当请求通过很多职责对象处理后,功能也就完成了,把这样的职责链称为功能链。

(2)应用举例

  ①实际开发中,在业务处理之前,通常需要进行权限检查、数据校验、逻辑检查等,然后才开始真正的业务逻辑。可以把这些功能分散到一个功能链中。

  ②过滤器:每个过滤器负责自己的处理,然后转交给下一个过滤器,直到把所有的过滤器都走完(如权限检查、字符转换等)。

【编程实验】字符过滤器(模拟JavaWeb的双向过滤器,变式的职责链模式

职责链模式的应用之模拟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);
}