C++设计模式之职责链模式(Chain of Responsibility)(行为型)

一 定义

在很多情况下,可以处理某个请求的对象不止一个,如大学里的奖学金审批,学生在向辅导员提交审批表之后,首先是辅导员签字审批,然后交给系主任签字审批,接着是院长审批,最后可能是校长审批,在这个过程中,奖学金申请表可以看成是一个请求对象,而不同级别的审批者都可以处理该请求对象,除了辅导员之外,学生不需要一一和其他审批者交互,只需等待结果即可。在审批过程中如果某一个审批者任务不符合条件,则请求中止;否则将请求递交给下一个审批者,最后由校长来确定谁能够授予奖学金。该过程如下:

在图中,从辅导员直到校长都可以处理申请表,而且他们构成了一条链,申请表沿着这条链传递,这条链就叫职责链。

职责链可以是一条直线,一个环或则一个树形结构,最常见的是直线型,即沿着一条单向的链来传递请求。链上的每一个对象都是请求处理者,职责链模式可以将请求的处理者组织成一条链,并使请求沿着链传递,由链上的处理者对请求进行相应的处理,客户端无须关心请求的处理细节以及请求的传递,只需将请求发送到链上即可,将请求的发送者和请求的处理者解耦。这就是职责链模式的模式动机。(客户类只需关心链的源头,而无需关心请求的处理细节及请求的传递过程)

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

二 ULM

角色:

抽象处理者(Handler)角色:定义出一个处理请求的接口(通常由一个Java抽象类或者Java接口实现)。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。
具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

优点

  • 责任链模式减低了发出命令的对象和处理命令的对象之间的耦合;
  • 处理者对于请求者完全透明,请求者无需事先知道谁来处理;
  • 它允许多与一个的处理者对象根据自己的逻辑来决定哪一个处理者最终处理这个命令,提高系统的扩展性;
  • 扩展灵活,新增具体请求者时无需修改原有系统的代码;

缺点

  • 产生许多细颗粒对象;
  • 不一定能被处理,可能到末端也没被处理或者中间写错;
  • 比较长的责任链,可能涉及多个处理对象,性能问题,还有调试不方便;
  • 建链不当,可能造成循环调用,导致系统进入死循环;

适用场景

  1. 多个对象可以处理同一请求,但具体由哪个对象处理,则需要动态决定时。
  2. 在请求者不明确的情况下需要向多个对象中的一个提交请求时。
  3. 需要动态的指定一组对象处理请求时。
  4. 系统已经有一个由处理者对象组成的链。这个链可能由复合模式给出,
  5. 当系统想发出一个请求给多个处理者对象中的某一个,但是不明显指定是哪一个处理者对象会处理此请求。
  6. 当处理一个请求的处理者对象集合需要动态地指定时。

三 实例

请假审批:某OA系统需要提供一个假条审批的模块,如果员工请假天数小于3天,主任可以审批该假条;如果员工请假天数大于等于3天,小于10天,经理可以审批;如果员工请假天数大于等于10天,小于30天,总经理可以审批;如果超过30天,总经理也不能审批,提示相应的拒绝信息。

ULM图

实现代码:

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include <iostream>
#include <string>
#include <memory>

//请求类LeaveRequest
class LeaveRequest
{
public:
    LeaveRequest(std::string leaveName, int leaveDays)
    {
        this->leaveName = leaveName;
        this->leaveDays = leaveDays;
    }

    void setLeaveName(std::string leaveName)
    {
        this->leaveName = leaveName;
    }

    void setLeaveDays(int leaveDays)
    {
        this->leaveDays = leaveDays;
    }

    std::string getLeaveName() const
    {
        return this->leaveName;
    }

    int getLeaveDays() const
    {
        return this->leaveDays;
    }
private:
    std::string leaveName;
    int leaveDays;
};

//抽象处理者Leader
class Leader
{
public:
    Leader(std::string name)
    {
        this->name = name;
    }

    void setSuccessor(std::weak_ptr<Leader> successor)
    {
        this->successor = successor;
    }

    virtual void handleRequest(const LeaveRequest& request) = 0;

protected:
    std::string name;
    std::weak_ptr<Leader> successor;
};

//具体处理者Director
class Director : public Leader
{
public:
    Director(std::string name) : Leader(name)
    {
    }

    void handleRequest(const LeaveRequest& request)
    {
        //处理请求
        if (request.getLeaveDays() < 3)
        {
            std::cout << "主任" << this->name << "审批员工" << request.getLeaveName() << "的请假条,请假天数为"
                << request.getLeaveDays() << "天." << std::endl;
        }
        else
        {
            //无法处理此请求,则交给上级处理
            if (this->successor.lock() != nullptr)
            {
                this->successor.lock()->handleRequest(request);
            }
        }
    }
};
//具体处理者Manager
class Manager : public Leader
{
public:
    Manager(std::string name) : Leader(name)
    {
    }

    void handleRequest(const LeaveRequest& request)
    {
        //处理请求
        if (request.getLeaveDays() < 10)
        {
            std::cout << "经理" << this->name << "审批员工" << request.getLeaveName() << "的请假条,请假天数为"
                << request.getLeaveDays() << "天." << std::endl;
        }
        else
        {
            //无法处理此请求,则交给上级处理
            if (this->successor.lock() != nullptr)
            {
                this->successor.lock()->handleRequest(request);
            }
        }
    }

};

//具体处理者GeneralManager
class GeneralManager : public Leader
{
public:
    GeneralManager(std::string name) : Leader(name)
    {
    }

    void handleRequest(const LeaveRequest& request)
    {
        //处理请求
        if (request.getLeaveDays() < 30)
        {
            std::cout << "总经理" << this->name << "审批员工" << request.getLeaveName() << "的请假条,请假天数为"
                << request.getLeaveDays() << "天." << std::endl;
        }
        else
        {
            std::cout << "莫非" << request.getLeaveName() << "想辞职,居然请假"
                << request.getLeaveDays() << "天." << std::endl;
        }
    }

};

//客户端测试
int main(void)
{
    std::shared_ptr<Leader> objDirector, objManager, objGeneralManager;

    //创建处理者
    objDirector = std::make_shared<Director>("王明");
    objManager = std::make_shared<Manager>("赵强");
    objGeneralManager = std::make_shared<GeneralManager>("李波");

    //设置上级
    objDirector->setSuccessor(objManager);
    objManager->setSuccessor(objGeneralManager);

    //职责链处理请求
    auto lr1 = std::make_shared<LeaveRequest>("张三", 2);
    objDirector->handleRequest(*lr1);

    auto lr2 = std::make_shared<LeaveRequest>("李四", 5);
    objDirector->handleRequest(*lr2);

    auto lr3 = std::make_shared<LeaveRequest>("王五", 15);
    objDirector->handleRequest(*lr3);

    auto lr4 = std::make_shared<LeaveRequest>("赵六", 45);
    objDirector->handleRequest(*lr4);

    return 0;
}

运行结果: