大家都在学校里呆了很多年,必然非常熟悉这样的情形,我们上课的时候想上厕所,直接向代课老师打报告,代课老师会直接同意,但是我们身体不适需要请假一两天的时候代课老师就没有这个权利,代课老师需要将我们的请求提交给班主任处理,这种事情班主任有权利直接批准,更甚至,如果我们中有像韩寒这样少年时就显露才华的人,想提出退学申请走文学道路的时候,班主任就会把申请提交给校长来权夺。
这就是责任链模式的典型应用场景,它包含了一些命令对象和一系列的处理对象,每个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给链中的下一个处理对象。在责任链模式中,发出请求的客户端并不知道链上的哪一个对象最终处理这个请求,这样系统就可以在不影响客户端程序的前提下重新分配链上的责任。
责任链模式的类图如下:
责任链模式中包含的角色有:
抽象处理者Handler:是一个抽象类,定义出一个处理请求的接口
具体处理者角色ConcreteHander:实现处理的接口,对于不同的命令,可以选择处理或者将请求传递给下一个处理对象
使用C++利用责任链模式来实现文章开始的那个例子:
#include "stdafx.h"
#include<iostream>
#include<string>
using namespace std;
class StudentRequest //学生请求类
{
public:
StudentRequest() :request(""){}
StudentRequest(string req) :request(req){}
~StudentRequest(){}
void setRequest(string req)
{
request=req;
}
string getRequest()
{
return request;
}
private:
string request;
};
class SchoolWorker //抽象处理者,学校工作人员
{
public:
virtual ~SchoolWorker(){}
virtual void processRequest(StudentRequest *sreq) = 0; //请求处理抽象接口
void setNextProcessor(SchoolWorker *nextProcessor) //设置下一级处理对象
{
mNextProcessor = nextProcessor;
}
protected:
SchoolWorker *mNextProcessor;
};
class classTeacher :public SchoolWorker //代课老师
{
public:
~classTeacher(){}
void processRequest(StudentRequest *sreq)
{
if (sreq->getRequest() == "去洗手间")
cout << "代课老师处理去洗手间请求" << endl;
else
mNextProcessor->processRequest(sreq);
}
};
class ClassManager :public SchoolWorker //班主任
{
public:
~ClassManager(){}
void processRequest(StudentRequest *sreq)
{
if (sreq->getRequest() == "请假")
cout << "班主任处理请假请求" << endl;
else
mNextProcessor->processRequest(sreq);
}
};
class Principal :public SchoolWorker //班主任
{
public:
~Principal(){}
void processRequest(StudentRequest *sreq)
{
if (sreq->getRequest() == "退学")
cout << "校长处理退学请求" << endl;
else
cout << "校长处理其他请求" << endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
StudentRequest* sreq = new StudentRequest("去洗手间");
SchoolWorker *clsstch = new classTeacher();
SchoolWorker *clssmng = new ClassManager();
SchoolWorker *prcpl = new Principal();
clsstch->setNextProcessor(clssmng);
clssmng->setNextProcessor(prcpl);
clsstch->processRequest(sreq);
sreq->setRequest("请假");
clsstch->processRequest(sreq);
sreq->setRequest("退学");
clsstch->processRequest(sreq);
delete sreq;
delete clsstch;
delete clssmng;
delete prcpl;
return 0;
}
运行结果: