职责链模式(Chain of Responsibility):
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
好比高中时候语文老师要在某个学习小组里找一个能背下来全篇长歌行的同学,点名第一个,第一个不会下一个,如此循环总会找到一个会的同学......
其中的关键就是当客户提交一个请求时,请求是沿着链传递,直到有一个对象负责处理它。
好处如下:
接收者和发送者都没有对方的明确信息,且链中的对象自己也不知道链的结构。结果是职责链可简化对象的相互连接,它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选接收者的引用。
由于是在客户端定义链的结构,可以随时地增加或者修改处理一个请求的结构。增强了给对象指派职责的灵活性。
注意:一个请求极有可能到了链的末端都得不到处理,或者因为没有正确的配置而得不到处理。比如上面我举的例子,如果整个组的同学都不会,那就尴尬了......
《大话设计模式》的图:
c++实现:
#include <iostream>
#include <string>
using namespace std;
//定义处理请示的接口
class Handler
{
protected:
Handler* successor;
public:
Handler() :successor(NULL) {}
virtual ~Handler() = 0 {}
void SetSuccessor(Handler* _suc)
{
successor = _suc;
}
virtual void HandleRequest(int request) = 0;
};
//具体处理类,处理负责的请求,无法处理就丢给后继者
class ConcreteHandler1 : public Handler
{
private:
string name;
public:
ConcreteHandler1(string _name) :name(_name) {}
~ConcreteHandler1() {}
void HandleRequest(int request)
{
if (request >= 0 && request < 10)
cout << name << " 处理请求 " << request << endl;
else if (successor != NULL)
successor->HandleRequest(request);
}
};
//同上
class ConcreteHandler2 : public Handler
{
private:
string name;
public:
ConcreteHandler2(string _name) :name(_name) {}
~ConcreteHandler2() {}
void HandleRequest(int request)
{
if (request >= 10 && request < 20)
cout << name << " 处理请求 " << request << endl;
else if (successor != NULL)
successor->HandleRequest(request);
}
};
//同上上
class ConcreteHandler3 : public Handler
{
private:
string name;
public:
ConcreteHandler3(string _name) :name(_name) {}
~ConcreteHandler3() {}
void HandleRequest(int request)
{
if (request >= 20)
cout << name << " 处理请求 " << request << endl;
else if (successor != NULL)
successor->HandleRequest(request);
}
};
int main()
{
Handler* h1 = new ConcreteHandler1(string("ConcreteHandler1"));
Handler* h2 = new ConcreteHandler2(string("ConcreteHandler2"));
Handler* h3 = new ConcreteHandler3(string("ConcreteHandler3"));
h1->SetSuccessor(h2);
h2->SetSuccessor(h3);
int request[] = { 2,5,14,44,22,15,23,12 };
for (int i : request)
{
h1->HandleRequest(i);
}
getchar();
return 0;
}
执行结果:
ConcreteHandler1 处理请求 2
ConcreteHandler1 处理请求 5
ConcreteHandler2 处理请求 14
ConcreteHandler3 处理请求 44
ConcreteHandler3 处理请求 22
ConcreteHandler2 处理请求 15
ConcreteHandler3 处理请求 23
ConcreteHandler2 处理请求 12
嗯......想到了状态模式(链接:https://blog.csdn.net/weixin_43272766/article/details/95215774)。感觉这两个模式都可以消除庞大的判断语句,职责链是客户端定义链的结构,使用上更加灵活,状态模式是内部自行判断的,客户端只能调用,没有灵活性,可是这样省内存,不需要像职责链那样提前定义好链的节点。还是根据具体的项目判断使用哪个吧。