定义

责任链模式(Chain of Responsibility Pattern)中,有一条由请求处理者对象组成的链条,每个对象(除最后一个对象外)都持有下一个对象的引用,请求发送者将请求发送给第一个对象,请求就会顺着链条走下去,直到有对象能够处理请求。该模式将多个处理者对象解耦,使得请求发送者只管将请求发送给责任链的第一个对象就是了,不用去关心请求具体是如何被处理的。

组成

抽象请求处理者(Abstract Request Handler):定义处理请求的接口,包括将请求处理掉和传给下一个对象。

具体请求处理者(Concrete Request Handler):持有下一个处理者对象的引用,具体实现处理请求的接口。

客户端(Client):将请求发送给责任链的头部对象。

举例

某学校的学生请假审批流程:

天数 <= 3:班主任审批通过;

3 < 天数 <= 7:班主任审批不通过,交给年级组长,年级组长审批通过;

7 < 天数 <= 30:年级组长审批不通过,交给教务处,教务处审批通过;

30 < 天数 <= 60:教务处审批不通过,交给校长,校长审批通过;

天数 > 60:校长审批不通过。

不用责任链模式写出的代码:

void handleRequest(int days)
{
    if (days <= 3)
    {
        cout << "班主任审批通过。" << endl;
    }
    else
    {
        cout << "班主任审批不通过。交给年级组长。" << endl;
        if (days <= 7)
        {
            cout << "年级组长审批通过。" << endl;
        }
        else
        {
            cout << "年级组长审批不通过。交给教务处。" << endl;
            if (days <= 30)
            {
                cout << "教务处审批通过。" << endl;
            }
            else
            {
                cout << "教务处审批不通过。交给校长。" << endl;
                if (days <= 60)
                {
                    cout << "校长审批通过。" << endl;
                }
                else
                {
                    cout << "校长审批不通过。" << endl;
                }
            }
        }
    }
}

可以看到,这段代码又是一堆if-else又是层层嵌套的,又臭又长,好难看!更重要的问题是,如果流程需要修改,那业务代码也需要修改,不符合开闭原则,难以维护和扩展。

那怎么样提高程序的可扩展性呢?

我们应该把班主任、年级组长等等拆分出来当做请求处理者,并指定一个共同的抽象父类,父类里面定义抽象接口,子类具体实现这些接口。

UML类图:

img

代码:

#include <iostream>

using namespace std;

/** 抽象处理者 */
class AbstractRequestHandler
{
protected:
    const char *name;

    const int maxDaysLimit;
    
    AbstractRequestHandler *const nextHandler; // 由于链条中最后一个处理者没有下一个处理者,但是c++不像java那样存在空引用,所以只能用指针了
    
    AbstractRequestHandler(
        const char *name,
        const int maxDaysLimit,
        AbstractRequestHandler *const nextHandler
    ) :
        name(name),
        maxDaysLimit(maxDaysLimit),
        nextHandler(nextHandler)
    { }

    virtual ~AbstractRequestHandler()
    {
        if (nextHandler)
        {
            delete nextHandler;
        }
    }
    
    virtual void handleRequest(int days)
    {
        if (days <= maxDaysLimit)
        {
            cout << name << "审批通过" << endl;
        }
        else
        {
            cout << name << "审批不通过";
            if (nextHandler)
            {
                cout << ",转交给" << nextHandler->name << endl;
                nextHandler->handleRequest(days);
            }
        }
    }

    friend class Client;
};

/** 具体处理者————校长 */
class Principal : public AbstractRequestHandler
{
public:
    Principal() : AbstractRequestHandler("校长", 60, nullptr) { }
};

/** 具体处理者————教务处 */
class AcademicAffairsOffice : public AbstractRequestHandler
{
public:
    AcademicAffairsOffice() : AbstractRequestHandler("教务处", 30, new Principal) { }
};

// 年级组长、班主任 略

/** 客户端 */
class Client
{
    HeadTeacher headTeacher;

public:
    Client() : headTeacher() { }

    void sendRequest(int days)
    {
        headTeacher.handleRequest(days);
    }
};

int main()
{
    Client client;
    int days = 10;
    cout << "学生将为期" << days << "天的请求交给班主任" << endl;
    client.sendRequest(days);
    return 0;
}