责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
常用场景1)
有一个请求数据,有一组handler, 其中的某一个handler可以用来处理该请求,可以将所有的handler连成一个chain,数据发送给第一个handler,其判断自己能否处理该数据,如果能则处理,并结束,否则, 调用下一个handler的处理函数,以此类推。
或者
客户发送了一个数据,该数据需要被各个环节进行检查,只有前面的检查通过后才进入下一个环节,可以将各个环节的检查函数抽象出来,将各个环节按照顺序连成一个链子。
常用场景2)
UI系统, 用户触发某个控件的一个signal, 该信号从子控件传递到上层父控件,层层前进,直到到达能够处理该signal的控件。
举例C++
Interface类为纯虚类定义公共的接口,ComponentBase类继承自接口类,定义各个具体的Component类的公共的部分, DogComponent为一个具体的类。
main函数中定义的链条: DogComponent对象 -> MonkeyComponent对象->ChickenComponent对象
#pragma once
#include <string>
#include <iostream>
#include <vector>
using namespace std;
/**
* The interface declares a method for building the chain of handlers.
* It also declares a method for executing a request.
*/
class Interface {
public:
Interface() {}
virtual ~Interface() {};
virtual Interface* setNextComponent(Interface* p) = 0;
virtual string handle(string sRequestData) = 0;
};
/**
* The default chaining behavior can be implemented inside a base handler class.
*/
class ComponentBase :public Interface {
public:
ComponentBase():
next(nullptr){
}
virtual ~ComponentBase() {
}
virtual string handle(string sRequestData) override{
if (next) {
return next->handle(sRequestData);
}
return "";
}
Interface* setNextComponent(Interface* nextComp) {
next = nextComp;
// Returning a handler from here will let us link handlers in a convenient way like this:
// $monkey->setNext($squirrel)->setNext($dog);
return nextComp;
}
Interface* getNextComponent() const {
return next;
}
protected:
Interface* next;
};
/**
* All Concrete Handlers either handle a request or pass it to the next handler
* in the chain.
*/
class DogComponent:public ComponentBase {
public:
DogComponent() {}
virtual ~DogComponent() {}
virtual string handle(string sRequestData) override {
if ("Shit" == sRequestData) {
return sRequestData + " was eated by Dog!\n";
}
else {
return ComponentBase::handle(sRequestData);
}
}
};
class MonkeyComponent :public ComponentBase {
public:
MonkeyComponent() {}
virtual ~MonkeyComponent() {}
virtual string handle(string sRequestData) override {
if ("Banana" == sRequestData) {
return sRequestData + " was eated by Monkey!\n";
}
else {
return ComponentBase::handle(sRequestData);
}
}
};
class ChickenComponent :public ComponentBase {
public:
ChickenComponent() {}
virtual ~ChickenComponent() {}
virtual string handle(string sRequestData) override {
if ("Rice" == sRequestData) {
return sRequestData + " was eated by Chicken! \n";
}
else {
return ComponentBase::handle(sRequestData);
}
}
};
/**
* The client code is usually suited to work with a single handler. In most
* cases, it is not even aware that the handler is part of a chain.
*/
void ClientCode(Interface &handler, const string& requestData) {
const std::string result = handler.handle(requestData);
if (!result.empty()) {
std::cout << " " << result;
}
else {
std::cout << " " << requestData << " was left untouched.\n";
}
}
int main() {
DogComponent* pDog = new DogComponent();
MonkeyComponent* pMonkey = new MonkeyComponent();
ChickenComponent* pChicken = new ChickenComponent();
pDog->setNextComponent(pMonkey)->setNextComponent(pChicken);
//入参也可时chain中间的某个元素,例如*pMonkey。
ClientCode(*pDog, "Shit");
return 1;
}
Ref:
https://refactoring.guru/design-patterns/chain-of-responsibility
https://refactoring.guru/design-patterns/chain-of-responsibility/cpp/example