Skip to content

责任链模式

回到目录

简介

参考链接

责任链模式主要用于处理请求,将处理请求的对象连成链,每个请求处理者都有着自己的处理权限.

意图:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求直到有一个对象处理它为止。

责任链模式,Chain of responsibility,是GoF中的behavior pattern行为模式中的一种,在所有的行为模式中,都设计的准则为:使用对象的组合而不是对象的继承。责任链模式所描述的是:与其从已有的类中继承新的类,不如让你的类指向一个你要使用的已经存在的类。该模式用于解耦发送请求的客户与处理请求的对象,实现方式为持有一系列的handler对象,每个对象都能处理特定的请求,如果某个handler不能处理该请求,它将请求传递给链中的下一个对象。在链的末端,会有一个或多个通用的(generic)handler,用于对请求的默认处理。

该模式为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

适用场景:不同的请求需要不同权限的对象来处理的情况

提升性

  • 在实际中对于责任链的设置多半是固定的,所以可以将之封装从而实现客户端的最少知道(迪米特原则)
  • 在责任链中设置最大结点数

优点

  • 将请求和处理分开,达到解耦。

缺点

链长度过长时就会有效率问题,其次是调试问题(这个问题也类似于递归)

总结 责任链可以作为一种补救措施.--中介者模式---模板方法模式

UML类图

代码示例

#include <iostream>
using namespace std;

class Handler
{
public:
    Handler() { m_pNextHandler = NULL; }
    //设置下一个处理者
    void SetNextHandler(Handler *successor) { m_pNextHandler = successor; }
    //处理请求
    virtual void HandleRequest(int days) = 0;
protected:
    Handler *m_pNextHandler;
};

// 主管处理者
class Director: public Handler
{
public:
  virtual void HandleRequest(int days) {
    if (days <= 1) {
      cout << "I am Director, agree request" << endl; 
    }
    else {
      m_pNextHandler->HandleRequest(days);
    }
  }
};

// 经理处理者
class Manager: public Handler
{
public:
  virtual void HandleRequest(int days) {
    if (days <= 3) {
      cout << "I am Manager, agree request" << endl;
    }
    else {
      m_pNextHandler->HandleRequest(days);
    }
  }
};

// 老板处理者
class Boss: public Handler
{
public:
  virtual void HandleRequest(int days) {
    if (days <= 7) {
      cout << "I am Manager, agree request" << endl;
    }
    else {
      cout << "days > 7, do not agree request" << endl;
    }
  }
};

int main()
{
  Handler *director = new Director;
  Handler *manager = new Manager;
  Handler *boss = new Boss;

  //设置责任链
  director->SetNextHandler(manager);
  manager->SetNextHandler(boss);

  director->HandleRequest(1);
  director->HandleRequest(2);
  director->HandleRequest(5);
  director->HandleRequest(8);

  delete director;
  delete manager;
  delete manager;

  return 0;
}