1.背景
当一个请求需要经过多个节点的处理,如果不考虑任何模式,每个对象要根据是否符合条件来决定是不是自己处理,这样就要使用if-else去处理。确定了类似A->B->C->D的处理流程后就不能再修改(除非修改源代码),导致客户端无法定制处理流程。再者各个节点的处理流程集中在一个类中,违反了"单一职责原则",将导致测试和维护难度加大;最后无法在运行时动态的增加、修改或者删除处理流程中的处理节点,灵活性缺失。
2.定义
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象能够处理它为止。发送请求的客户端并不知道链上的哪个对象会处理这个请求,这使得系统在不影响客户端的情况下动态的组织和分配责任。
纯的责任链模式
一个纯的职责链模式要求一个具体处理者对象只能在两个行为中选择一个:要么承担全部责任,要么将责任推给下家,不允许出现某一个具体处理者对象在承担了一部分或全部责任后又将责任向下传递的情况。而且在纯的职责链模式中,要求一个请求必须被某一个处理者对象所接收,不能出现某个请求未被任何一个处理者对象处理的情况。
不纯的责任链模式
在一个不纯的职责链模式中允许某个请求被一个具体处理者部分处理后再向下传递,或者一个具体处理者处理完某请求后其后继处理者可以继续处理该请求,而且一个请求可以最终不被任何处理者对象所接收。
注:在实际软件系统中,很少能找到纯的责任链模式,大多数情况是不纯的责任链模式。
3.组成结构
- Client(客户端):向处理者提交请求对象。
- Handler(抽象处理者):定义了一个处理请求的接口,设计为抽象类,由于不同的具体处理者处理请求的方式不同,因此在其中定义了抽象请求处理方法。持有下一个抽象处理者的引用,通过该引用,处理者可以连成一条链。
- ConcreteHandler(具体处理者):抽象处理者的子类,可以处理用户请求,在具体处理者类中实现了抽象处理者中定义的抽象请求处理方法,在处理请求之前需要进行判断,看是否有相应的处理权限,如果可以处理请求就处理它,否则将请求转发给后继者;在具体处理者中可以访问链中下一个对象,以便请求的转发。
4.示例代码
cpp
#include <iostream>
using namespace std;
//抽象处理者
class Handler
{
public:
Handler() { m_pNextHandler = NULL; }
virtual ~Handler() {}
//设置下一个处理者
void SetNextHandler(Handler* successor) { m_pNextHandler = successor; }
//处理请求
virtual void HandleRequest(int days) = 0;
protected:
Handler* m_pNextHandler; // 后继者
};
//具体处理者、主管
class Director :public Handler
{
public:
//处理请求
virtual void HandleRequest(int days)
{
if (days <= 1)
{
cout << "我是主管,有权批准一天假,同意了!" << endl;
}
else
{
m_pNextHandler->HandleRequest(days);
}
}
};
//具体处理者、经理
class Manager :public Handler
{
public:
//处理请求
virtual void HandleRequest(int days)
{
if (days <= 3)
{
cout << "我是经理,有权批准三以下的假,同意了!" << endl;
}
else
{
m_pNextHandler->HandleRequest(days);
}
}
};
//具体处理者、老板
class Boss :public Handler
{
public:
//处理请求
virtual void HandleRequest(int days)
{
if (days <= 7)
{
cout << "我是老板,最多让你请7天假,同意了!" << endl;
}
else
{
cout << "你请的假事假太长了,不同意!" << endl;
}
}
};
//场景
int main()
{
Handler* director = new Director;
Handler* manager = new Manager;
Handler* boss = new Boss;
//设置责任链
director->SetNextHandler(manager);
manager->SetNextHandler(boss);
director->HandleRequest(1);
director->HandleRequest(2);
director->HandleRequest(5);
director->HandleRequest(8);
return 0;
}
/*结果:
我是主管,有权批准一天假,同意了!
我是经理,有权批准三以下的假,同意了
我是老板,最多让你请7天假,同意了!
你请的假事假太长了,不同意!
请按任意键继续. . .*/
引用
https://blog.csdn.net/Golden_Knight/article/details/103363616