责任链模式 行为型模式
责任链模式在实际项目中的应用相当广泛,特别是那些需要多个对象可能参与处理单个请求的情境。
常用实例:
-
审批流程: 在企业管理系统中,一个请假或报销申请可能需要通过不同层级的审批。例如,员工提交一个请假请求,请求首先会被直接上级审批,如果上级批准,请求会传递到部门经理,最终可能到达人力资源部。如果某一级别的审批者拒绝,请求处理流程将终止。
-
GUI事件传播: 在图形用户界面(GUI)框架中,一个事件(如鼠标点击)可能由一个组件到另一个组件传递,直到找到一个愿意处理该事件的组件为止。比如,点击事件首先被顶级窗口捕获,如果顶级窗口不处理,它就会将事件传递给下一层次的子窗口,以此类推。
-
日志处理: 在复杂的系统中,日志消息可能需要根据其严重性级别(如debug、info、warning、error)在不同的日志处理器之间传递。每个处理器决定它是否要处理该日志消息,还是将其传递到责任链的下一个处理器。
-
中间件: 在Web应用框架中,请求可以通过一系列中间件进行处理。每个中间件执行其功能(如身份验证、日志记录、数据验证等),然后选择是结束请求还是将其传递到下一个中间件。
-
命令对象处理: 在命令模式中,命令对象可以被责任链模式处理,例如,一个具有撤销功能的系统可能会使用责任链来查找能够处理撤销操作的命令对象。
-
游戏编程: 在游戏开发中,游戏中的事件(如攻击、使用道具等)可以通过责任链传递给多个监听者,每个监听者可能是不同的游戏对象(如玩家、敌人或障碍物),直到事件被处理。
-
支付处理: 在电子商务系统中,支付请求可能需要经过一系列不同的支付处理步骤,比如优惠券应用、积分抵扣、实际的支付处理等。每个步骤都可以作为责任链上的一个节点。
类图:
代码:
#include "iostream"
#include "string"
#include "vector"
using namespace std;
class Handler
{
public:
virtual Handler*SetNext(Handler*handler)=0;
virtual string Handle(string request)=0;
};
class AbstracHansler :public Handler {
public:
AbstracHansler():next_handler_(nullptr){}
Handler* SetNext(Handler* handler)
{
this->next_handler_=handler;
return handler;
};
string Handle(string request)
{
if (this->next_handler_)
{
return next_handler_->Handle(request);
}
return {};
};
protected:
Handler*next_handler_;
};
class ConcreteHandler1 :public AbstracHansler
{
public:
string Handle(string request)
{
if (request == "Request1")
{
return "ConcreteHandler1: I'll handle the Request1.\n";
}
else
{
return AbstracHansler::Handle(request);
}
}
};
class ConcreteHandler2 :public AbstracHansler
{
public:
string Handle(string request)
{
if (request == "Request2")
{
return "ConcreteHandler2: I'll handle the Request2.\n";
}
else
{
return AbstracHansler::Handle(request);
}
}
};
class ConcreteHandler3 :public AbstracHansler
{
public:
string Handle(string request)
{
if (request == "Request3")
{
return "ConcreteHandler3: I'll handle the Request3.\n";
}
else
{
return AbstracHansler::Handle(request);
}
}
};
void ClientCode(Handler& handler)
{
for (string request : {"Request3", "Request2", "Request1"})
{
cout<< "Client: Who wants to handle " << request << "?\n";
const string result=handler.Handle(request);
if (!result.empty())
{
cout<<" "<<result;
}
else
{
cout<<" "<<request<< " was left untouched.\n";
}
}
}
int main()
{
ConcreteHandler1*handler1=new ConcreteHandler1;
ConcreteHandler2*handler2=new ConcreteHandler2;
ConcreteHandler3*handler3=new ConcreteHandler3;
handler1->SetNext(handler2);
cout<< "Chain: ConcreteHandler1 > ConcreteHandler2\n\n";
ClientCode(*handler1);
delete handler1;
delete handler2;
return 0;
}