面向对象设计原则
接口隔离原则:面向对象设计之接口隔离原则-CSDN博客
设计模式工厂模式 : 设计模式之工厂模式-CSDN博客
迭代器模式:设计模式之迭代器模式-CSDN博客
适配器模式:设计模式之适配器模式-CSDN博客
过滤器模式:设计模式之过滤器模式-CSDN博客
单例模式:设计模式之单例模式-CSDN博客
观察者模式:设计模式之观察者模式-CSDN博客
空对象模式:设计模式之空对象模式-CSDN博客
桥接模式:设计模式之桥接模式-CSDN博客
策略模式:设计模式之策略模式-CSDN博客
责任链模式:设计模式之责任链模式-CSDN博客
目录
1.概述
责任链模式(Chain of Responsibility Pattern)是一种行为性设计模式;它为请求创建了一个接收者对象的链,允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。这种处理方法类似包与包之间的调用的思路,只是其可以不在主程序中累赘的去申明一堆if else变量使得程序更加臃肿。在我的博客中就是利用责任链模式来消除多层if-else-if。
2.结构
责任链模式的重点是在"链"上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果,其通用类图如下图所示:
角色定义:
抽象处理者(Handler): 定义一个处理请求的接口,通常包含一个处理请求的方法(如
handleRequest
)和一个指向下一个处理者的引用(后继者),一般这类情况class内部都是纯虚函数。
**具体处理者(ConcreteHandler):**实现了抽象处理者接口,负责处理请求。如果能够处理该请求,则直接处理;否则,将请求传递给下一个处理者;这样可以通过设计整个逻辑链避免混乱。
**客户端(Client):**创建处理者对象,并将它们连接成一条责任链。通常,客户端只需要将请求发送给责任链的第一个处理者,无需关心请求的具体处理过程。
3.实现
以公司的请假为例,普通员工请假小于等于2天只需要自己的组长同意,请假大于2天小于等于5天需要部门经理同意,大于5天小于10天需要公司总经理同意才行,大于10天的请不了。根据上面的需求,我们可以先抽象Handler,再定义组长、部门经理、总经理,代码如下:
cpp
#include <iostream>
using namespace std;
//抽象处理者
class Handler
{
public:
explicit Handler() { m_pNextHandler = NULL; }
virtual ~Handler() {}
//设置下一个处理者
void setNextHandler(Handler *successor) { m_pNextHandler = successor; }
//处理请求
virtual void HandleRequest(int days) = 0;
protected:
Handler *m_pNextHandler; // 后继者
};
//组长
class CGroupLeader : public Handler
{
public:
//处理请求
void HandleRequest(int days) override
{
if (days <= 2)
{
cout << "我是组长,有权批准" << days << "天假,同意了!" << endl;
}
else
{
m_pNextHandler->HandleRequest(days);
}
}
};
//部门经理
class CDeptManager : public Handler
{
public:
//处理请求
void HandleRequest(int days) override
{
if (days <= 5)
{
cout << "我是部门经理,有权批准" << days << "天的假,同意了!" << endl;
}
else
{
m_pNextHandler->HandleRequest(days);
}
}
};
//总经理
class CGeneralManager : public Handler
{
public:
//处理请求
void HandleRequest(int days) override
{
if (days <= 10)
{
cout << "我是总经理,最多让你请10天假,同意了!" << endl;
}
else
{
cout << "你请的假时间太长了,不同意!" << endl;
}
}
};
测试用例:
cpp
#include <memory>
int main()
{
std::unique_ptr<Handler> pGroupLeader = new CGroupLeader;
std::unique_ptr<Handler> pDeptLeader = new CDeptManager;
std::unique_ptr<Handler> pGeneralManager = new CGeneralManager;
//设置责任链
pGroupLeader->setNextHandler(pDeptLeader.get());
pDeptLeader->setNextHandler(pGeneralManager.get());
pGroupLeader->HandleRequest(1);
pGroupLeader->HandleRequest(2);
pGroupLeader->HandleRequest(5);
pGroupLeader->HandleRequest(8);
pGroupLeader->HandleRequest(12);
return 0;
}
输出:
cpp
我是组长,有权批准1天假,同意了!
我是组长,有权批准2天假,同意了!
我是部门经理,有权批准5天的假,同意了!
我是总经理,最多让你请10天假,同意了!
你请的假时间太长了,不同意!
4.总结
优点:
解耦: 责任链模式将请求的发送者和接收者解耦,请求的发送者不需要知道接收者是谁,也不需要创建接收者的实例。同时,接收者也不需要知道请求的具体内容,只需要按照自已的业务逻辑进行相应的处理。这种解耦方式使得系统更加灵活,降低了耦合度,方便进行模块化开发和测试。
链式处理:责任链模式可以形成一个处理链,请求在这个链中传递,每个节点都会对请求进行处理,这种方式可以实现复杂的业务逻辑,提高系统的可扩展性和可维护性。
动态添加节点:在运行时,可以通过动态添加或册除节点来改变处理链,从而实现动态地扩展或修改处理逻辑。这种动态性使得系统更加灵活,能够适应不同的需求变化。
缺点:
错误传播:在责任链模式中,如果某个节点处理请求时出现了错误,这个错误会沿看处理链向上传播,可能会导致整个链路崩溃。为了解决这个问题,需要确保每个节点都进行了错误处理,能够在出现错误时进行适当的处理或回退操作。
无法终止链路:在某些情况下,如果请求不满足某个节点的条件,该节点就不需要对请求进行处理,但责任链模式无法直接终止链路。为了解决这人问题,可以在节点中添加判断逻辑,当请求不满足条件时直接返可或者进行其他处理。
性能问题:由于请求会在多个节点间传递,因此责任链模式的性能可能会受到影响。特别是在请求量较大或处理逻辑较复杂的情况下,这种影响会更加明显。为了解决这个问题,可以对节点进行优化,提高处理效率,同时也可以考虑使用缓存等方式来降低请求的重复处理。
节点之间的依赖关系:在责任链模式中节点之间存在依赖关系,如果每个节点的处理逻辑发生了变化,可能会影响到其它节点。这种依频关系可能会导致系统复杂度增加,增加了维护的难度。为了避免这种情况,可以尽量减少节点之间的依赖关系,使每个节点都尽可能独立地处理请求。同时也可以采用模块化设计等方式来降低系统复杂度。