属于“数据结构”模式,因为责任链实际是一个单链表的形式。
还有:

  1. Composite:构成一个树形结构
  2. Iterator:处理容器内部数据结构和外部依赖关系的过程,是一个遍历的动作

动机

在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显示指定,将必不可少地带来请求者接受者的紧耦合。

如何使请求者不需要指定具体的接受者?让请求的接受者自己在运行时决定谁来处理请求,从而使两者解耦。

模式定义

使多个对象都有机会处理请求,从而避免请求者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。——《设计模式》GoF。

代码

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. //请求类型
  5. enum class RequestType
  6. {
  7. REQ_HANDLER1,
  8. REQ_HANDLER2,
  9. REQ_HANDLER3
  10. };
  11. //请求
  12. class Reqest
  13. {
  14. string description; //描述
  15. RequestType reqType; //请求类型
  16. public:
  17. Reqest(const string & desc, RequestType type) : description(desc), reqType(type) {}
  18. //得到请求类型
  19. RequestType getReqType() const { return reqType; }
  20. const string& getDescription() const { return description; }
  21. };
  22. //责任链
  23. //核心逻辑:责任链上有很多个处理类,如果当前节点不能处理,则交给下一个处理,直到处理完成
  24. class ChainHandler{
  25. ChainHandler *nextChain; //下一个处理者
  26. //将请求发送给下一个请求者
  27. void sendReqestToNextHandler(const Reqest & req)
  28. {
  29. if (nextChain != nullptr)
  30. nextChain->handle(req);
  31. }
  32. protected:
  33. //this能否处理这个请求
  34. virtual bool canHandleRequest(const Reqest & req) = 0;
  35. //用this处理这个请求
  36. virtual void processRequest(const Reqest & req) = 0;
  37. public:
  38. ChainHandler() { nextChain = nullptr; }
  39. //设置下一个节点
  40. void setNextChain(ChainHandler *next) { nextChain = next; }
  41. //处理
  42. void handle(const Reqest & req)
  43. {
  44. //this是否能处理这个请求
  45. if (canHandleRequest(req))
  46. //可以 -> 处理这个请求
  47. processRequest(req);
  48. else
  49. //不可以,发送给下一个
  50. sendReqestToNextHandler(req);
  51. }
  52. };
  53. //第一个处理者
  54. class Handler1 : public ChainHandler{
  55. protected:
  56. bool canHandleRequest(const Reqest & req) override
  57. {
  58. //this是处理RequestType::REQ_HANDLER1类型的请求
  59. return req.getReqType() == RequestType::REQ_HANDLER1;
  60. }
  61. void processRequest(const Reqest & req) override
  62. {
  63. //处理
  64. cout << "Handler1 is handle reqest: " << req.getDescription() << endl;
  65. }
  66. };
  67. //第二个处理者
  68. class Handler2 : public ChainHandler{
  69. protected:
  70. bool canHandleRequest(const Reqest & req) override
  71. {
  72. return req.getReqType() == RequestType::REQ_HANDLER2;
  73. }
  74. void processRequest(const Reqest & req) override
  75. {
  76. cout << "Handler2 is handle reqest: " << req.getDescription() << endl;
  77. }
  78. };
  79. //第三个处理者
  80. class Handler3 : public ChainHandler{
  81. protected:
  82. bool canHandleRequest(const Reqest & req) override
  83. {
  84. return req.getReqType() == RequestType::REQ_HANDLER3;
  85. }
  86. void processRequest(const Reqest & req) override
  87. {
  88. cout << "Handler3 is handle reqest: " << req.getDescription() << endl;
  89. }
  90. };
  91. int main(){
  92. //创建责任链
  93. Handler1 h1;
  94. Handler2 h2;
  95. Handler3 h3;
  96. h1.setNextChain(&h2);
  97. h2.setNextChain(&h3);
  98. //创建一个请求
  99. Reqest req("process task ... ", RequestType::REQ_HANDLER3);
  100. //用责任链处理请求
  101. h1.handle(req);
  102. return 0;
  103. }

结构

image.png

要点总结

要点一

【要点一】职责链模式的应用场景在于“一个请求可能有多个接受者,但是最后真正的接受者只有一个”
这时候请求发送者与接受者的耦合有可能出现“变化脆弱”的症状,职责链的目的就是将二者解耦,从而更好地应对变化。

【核心思想】请求者,只需把球踢给第一个处理者,至于以后怎么办,具体是谁处理的。请求者并不关心,他只关心你处理的结果。

要点二

【要点二】应用了职责链模式后,对象的职责分派将更具有灵活性。如果可以在运行时动态添加/修改请求的处理职责。

要点三

【要点三】如果请求传递到职责链的末尾仍得不到处理,应该有一个合理的缺省机制。这也是每个接受对象的责任,而不是发出请求对象的责任。