责任链模式

允许多个对象依次处理请求,直到其中某个对象处理该请求为止。这样可以避免请求的发送者和接收者之间的耦合,使多个对象都有机会处理请求。

c2c611c2bfdd2bde4adfe1d6931f1d10.png
  • 每个处理者(Handler)都持有对下一个处理者的引用
  • 处理者决定是否处理请求,或者将请求传递给下一个处理者
  • 客户端只需要将请求提交给责任链的起点,而不需要关心最终的处理者是谁
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
enum class LOGLEVEL {
Y_INFO,
Y_WARN,
Y_ERROR
};

// 责任对象的基类
class Logger {
protected:
LOGLEVEL level;
Logger* nextLogger_;
public:
explicit Logger(LOGLEVEL level) : level(level), nextLogger_(nullptr) {}

virtual ~Logger() = default;

void setNext(Logger* nextLogger) {
nextLogger_ = nextLogger;
}

void Log(LOGLEVEL loglevel, const std::string &msg) { // 责任对象的选择
if (loglevel >= level){
writeMsg(msg);
}
if (nextLogger_ != nullptr) {
nextLogger_->Log(loglevel, msg);
}
}

public:
virtual void writeMsg(const std::string &msg) = 0;

};

class infoLogger : public Logger {
public:
explicit infoLogger(LOGLEVEL level) : Logger(level) {}

void writeMsg(const std::string &msg) override {
if (level == LOGLEVEL::Y_INFO) {
std::cout << "[" << "INFO: " << msg << "]" << std::endl;
} else {
nextLogger_->writeMsg(msg);
}
}
};

class warnLogger : public Logger {
public:
explicit warnLogger(LOGLEVEL level) : Logger(level) {}

void writeMsg(const std::string &msg) override {
if (level == LOGLEVEL::Y_WARN) {
std::cout << "[" << "WARN: " << msg << "]" << std::endl;
} else {
nextLogger_->writeMsg(msg);
}
}
};

class errorLogger : public Logger {
public:
explicit errorLogger(LOGLEVEL level) : Logger(level) {}

void writeMsg(const std::string &msg) override {
if (level == LOGLEVEL::Y_ERROR) {
std::cout << "[" << "ERROR: " << msg << "]" << std::endl;
} else {
nextLogger_->writeMsg(msg);
}
}
};

责任对象之间还并没有建立联系,因此得创建一个函数来将这些责任连接起来,返回最初的责任对象即可:

1
2
3
4
5
6
7
8
9
10
11
// 构建责任链关系,返回最开始的责任对象
Logger* createLoggerChain() {
Logger* info = new infoLogger(LOGLEVEL::Y_INFO);
Logger* warn = new warnLogger(LOGLEVEL::Y_WARN);
Logger* error = new errorLogger(LOGLEVEL::Y_ERROR);

info->setNext(warn);
warn->setNext(error);

return info;
}

此后,用户在使用的时候,只需要通过 createLoggerChain 得到责任链的起始端,然后调用基类提供的 Log 方法即可,内部会根据用户的请求来判断当前责任对象是不是能处理,不能处理就往下传递,如此反复,直到责任终止。