一、概述
描述:如组长不能处理的金额,需要向经理请求,经理不能请求的需要向老板请求,这样就现成了一条链,每个级别都能处理这金额。而不是直接组长向老板请求。无需关心请求的处理细节以及请求的传递,只需将请求发送到链上。将请求的发送者和处理者解耦,是职责链模式的动机。
定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
二、结构
-
处理者(Handler)声明了所有具体处理者的通用接口。该接口通常仅包含单个方法用于请求处理,但有时其还会包含一个设置链上下个处理者的方法。
-
基础处理者(Base Handler)是一个可选的类, 你可以将所有处理者共用的样本代码放置在其中。通常情况下,该类中定义了一个保存对于下个处理者引用的成员变量。客户端可通过将处理者传递给上个处理者的构造函数或设定方法来创建链。该类还可以实现默认的处理行为:确定下个处理者存在后再将请求传递给它。
-
具体处理者(Concrete Handlers)包含处理请求的实际代码。每个处理者接收到请求后,都必须决定是否进行处理,以及是否沿着链传递请求。处理者通常是独立且不可变的,需要通过构造函数一次性地获得所有必要地数据。
-
客户端(Client)可根据程序逻辑一次性或者动态地生成链。值得注意的是,请求可发送给链上的任意一个处理者,而非必须是第一个处理者。
对于职责链中的一个处理者对象,有两个行为:一是处理请求,二是将请求传递到下一节点,不允许某个处理者对象在处理了请求后又将请求传送给上一个节点的情况。
职责链可以分为两种情况:纯的职责链模式和不纯的职责链模式
-
纯的职责链模式要求一个具体的处理者对象只能在两个行为中选择一个:要么承担全部责任,要么将责任推给下家,不允许出现某一个具体处理者承担了一部分或者全部责任后又将责任向下传递。而且一个请求必须被某一个处理者所接受,不能出现某个请求未被任何一个处理者对象处理的情况。
-
不纯的职责链模式,允许某个请求被一个具体处理者部分处理后向下传递,或者一个具体处理者处理完某个请求后其后续处理者可以继续处理该请求,而且一个请求可以最终不被任何处理者对象接受并处理。
三、适用场景
- .有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定;
- 在不明确指定接受者的情况下,向多个对象中的一个提交一个请求;
- 可动态指定一组对象处理请求,客户端可以动态创建职责链来处理请求
四、优缺点
优点:
- 责任链模式减低了发出命令的对象和处理命令的对象之间的耦合;
- 处理者对于请求者完全透明,请求者无需事先知道谁来处理;
- 它允许多与一个的处理者对象根据自己的逻辑来决定哪一个处理者最终处理这个命令,提高系统的扩展性;
- 扩展灵活,新增具体请求者时无需修改原有系统的代码;
缺点:
- 产生许多细颗粒对象;
- 不一定能被处理,可能到末端也没被处理或者中间写错;
- 比较长的责任链,可能涉及多个处理对象,性能问题,还有调试不方便;
- 建链不当,可能造成循环调用,导致系统进入死循环;
五、实例
#include<iostream>
#include<string>
using namespace std;
// 抽象处理者, 在C++中是抽象基类,提供接口
class ApproverInteerace {
public:
// 添加上级
virtual void setSuperior(ApproverInteerace* superior) = 0;
// 处理票据申请, 参数是票据面额
virtual void handleRequest(double amount) = 0;
};
class BaseApprover :public ApproverInteerace {
private:
double max_processilbe_amount_;// 可处理的最大面额
string name_;
ApproverInteerace* superior_;
public:
BaseApprover(double mpa, string n) :max_processilbe_amount_(mpa), name_(n), superior_(nullptr) {}
// 设置上级
void setSuperior(ApproverInteerace* superior) {
superior_ = superior;
}
// 处理票据
void handleRequest(double amount)
{
// 可处理时直接处理即可
if (amount <= max_processilbe_amount_) {
printf("%s处理了该票据, 票据面额:%f\n", name_.c_str(), amount);
return;
}
// 无法处理时移交给上级
if (superior_ != nullptr) {
printf("%s无权处理, 转交上级...\n", name_.c_str());
superior_->handleRequest(amount);
return;
}
// 最上级依然无法处理时报错
printf("无人有权限处理该票据, 票据金额:%f\n", amount);
}
};
// 具体处理者: 组长(仅处理面额<=10的票据)
class GroupLeader : public BaseApprover {
public:
explicit GroupLeader(string name) : BaseApprover(10, name) {}
};
// 具体处理者: 经理(仅处理面额<=100的票据)
class Manager : public BaseApprover {
public:
explicit Manager(string name) : BaseApprover(100, name) {}
};
// 具体处理者: 老板(仅处理面额<=1000的票据)
class Boss : public BaseApprover {
public:
explicit Boss(string name) : BaseApprover(1000, name) {}
};
int main()
{
// 请求处理者: 组长、经理和老板
GroupLeader* group_leader = new GroupLeader("张组长");
Manager* manager = new Manager("王经理");
Boss* boss = new Boss("李老板");
group_leader->setSuperior(manager);
manager->setSuperior(boss);
// 不同面额的票据统一先交给组长审批
group_leader->handleRequest(8);
group_leader->handleRequest(88);
group_leader->handleRequest(888);
group_leader->handleRequest(8888);
delete group_leader;
delete manager;
delete boss;
return 0;
}