允许多个对象依次处理请求,直到其中某个对象处理该请求为止。这样可以避免请求的发送者和接收者之间的耦合,使多个对象都有机会处理请求。
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
方法即可,内部会根据用户的请求来判断当前责任对象是不是能处理,不能处理就往下传递,如此反复,直到责任终止。