思考职责链模式
①职责链的本质:分离职责,动态组合。分离职责是前提,动态组合才是职责链模式的精华所在,因为这意味着可以很方便地修改和添加新的处理对象,从而让系统更加灵活和具有更好的扩展性。
②职责链的动机:在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时需要有接受者,如果显式指定,将必不可少地带来请求发送者与接受者之间的紧耦合。而职责链模式可以将这两者解耦,使得发送者不必知道具体的接受者(处理者)
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); }