职责链模式:

  在现实生活中,常常会出现这样的事例:一个请求需要多个对象处理,但每个对象的处理条件或权限不同。如公司员工报销差旅费,可审批的领导有部分负责人、副总经理、总经理等,但每个领导能审批的金额是不同的,不同的金额需要找相应的领导审批,也就是说要报销必须先搞清楚需要谁来审批。职责链模式就是为了解决这样的问题产生的。

  职责链模式,又叫责任链模式。是为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一个对象记住其下一个对象的引用而连成一条链。当发生请求时,可将请求沿着这条链传递,直到有对象处理它为止。

职责链模式的角色:

  1. 抽象处理者(Handler):声明了所有具体处理者的通用接口。 该接口通常仅包含单个方法用于请求处理, 但有时其还会包含一个设置链上下个处理者的方法
  2. 具体处理者(ConcreteHandler):包含处理请求的实际代码。 每个处理者接收到请求后, 都必须决定是否进行处理, 以及是否沿着链传递请求。处理者通常是独立且不可变的, 需要通过构造函数一次性地获得所有必要地数据。
  3. 请求信息(Request):定义请求的信息。
  4. 客户端(Client):可根据程序逻辑一次性或者动态地生成链。值得注意的是,请求可发送给链上的任意一个处理者,而非必须是第一个处理者。

优点:

  1. 请求者和接收者松耦合。在职责链模式中,请求者并不知道接收者是谁,也不知道具体如何处理,请求者只是负责向职责链发送请求就可以了。而每个职责对象也不用管请求者或者是其他的职责对象,只负责处理自己的部分,其他的就交给其他的职责对象去处理。也就是说,请求者和接受者是完全解耦的。
  2. 动态组合职责。职责链模式会把功能处理分散到单独的职责对象中,然后再使用的时候,可以动态组合职责形成职责链,从而可以灵活地给对象分配职责,也可以灵活地实现和改变对象的职责。
  3. 减少代码中的if..else..判断,优化代码。

缺点:

  1. 产生很多细粒度对象。职责链模式会把功能处理分散到单独的职责对象中,也就是每个职责对象只处理一个方面的功能,要把整个业务处理完,需要很多职责对象的组合,这样会产生大量的细粒度职责对象。
  2. 不一定能被处理。职责链模式的每个职责对象只负责自己处理的那一部分,因此可能会出现某个请求把整个链传递完了都没有职责对象处理它。这就需要使用职责链模式的时候,需要提供默认的处理,并且注意构造的链的有效性。
  3. 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能由于职责链的错误设置而导致系统出错,如可能会造成循环调用。

职责链的应用场景:

  1. 有多个对象可以处理一个请求,哪个对象处理该请求由运行时刻自动确定。
  2. 可动态指定一组对象处理请求,或添加新的处理者
  3. 在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。

eg:

class Manager
{
protected:
    Manager *m_manager;
    string m_name;
public:
    Manager(Manager* manager,string name):m_manager(manager),m_name(name){}
    virtual void DealWithRequest(string name, int num) {}
};

//--------------------------------------------------
class CommonManager : public Manager
{
public:
    CommonManager(Manager* manager,string name):Manager(manager,name){}
    void DealWithRequest(string name,int num)
    {
        if(num < 500)
        {
            cout << "经理" <<m_name << "批准" << name << "加薪" << num << "元" <<endl;
        }
        else
        {
            cout << "经理" << m_name << "无法处理,交由总监处理" <<endl;
            m_manager->DealWithRequest(name,num);
        }
    }
};

class Majordomo:public Manager
{
public:
    Majordomo(Manager *manager,string name):Manager(manager,name){}
    virtual void DealWithRequest(string name,int num)
    {
        if(num < 1000)
        {
            cout << "总监" <<m_name << "批准" << name << "加薪" << num << "元" <<endl;
        }
        else
        {
            cout << "总监" << m_name << "无法处理,交由总经理处理" <<endl;
            m_manager->DealWithRequest(name,num);
        }
    }
};

class GeneralManager : public Manager
{
public:
    GeneralManager(Manager *manager,string name):Manager(manager,name){}
    void DealWithRequest(string name,int num)
    {
        cout << "总经理" <<m_name << "批准" << name << "加薪" << num << "元" <<endl;
    }
};

//--------------------------------------------------
//use
    Manager *general = new GeneralManager(NULL,"a");
    Manager *majordomo = new Majordomo(general,"b");
    Manager *common = new CommonManager(majordomo,"c");
    common->DealWithRequest("d",400);
    common->DealWithRequest("d",700);
    common->DealWithRequest("d",1200);