职责链模式

什么是职责链模式

在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

为什么要使用

解耦了请求者与处理者。

常见的职责链模式

  1. 语言的异常机制,一个 try 对应多个 catch
  2. 请假审批
  3. 轮流出牌

类型

行为型模式

参与者

  1. Client 发出请求,构造职责链。
  2. Handler 抽象的处理类
    • 定义一个请求处理接口
    • 定义链上的下一个接口
  3. ConcreteHandler 具体的处理类

例子

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
<?php
/**
* 请假审批
*/

/**
* 请假类
* Class LeaveRequest
*/
class LeaveRequest {
public $empName;
public $leaveDays;
public $reason;

public function __construct($empName, $leaveDays, $reason)
{
$this->empName = $empName;
$this->leaveDays = $leaveDays;
$this->reason = $reason;
}
}

/**
* 责任人
* Class Leader
*/
abstract class Leader {
protected $name;
/**
* @var Leader
*/
protected $nextLeader;

public function __construct($name)
{
$this->name = $name;
}

public function setNextLeader(Leader $nextLeader)
{
$this->nextLeader = $nextLeader;
}

public abstract function handleRequest(LeaveRequest $leaveRequest);
}


/**
* 主管
* Class Direct
*/
class Director extends Leader {

public function __construct($name)
{
parent::__construct($name);
}

/**
* 主管能批准三天以下的请假
* @param LeaveRequest $leaveRequest
*/
public function handleRequest(LeaveRequest $leaveRequest)
{
if ($leaveRequest->leaveDays <= 3) {
echo '请假人'.$leaveRequest->empName.',天数:'.$leaveRequest->leaveDays.',理由:'.$leaveRequest->reason.PHP_EOL;
echo '审批人:'.$this->name.PHP_EOL;
} else {
if (!empty($this->nextLeader)) {
$this->nextLeader->handleRequest($leaveRequest);
}
}
}
}

/**
* 经理
* Class Manager
*/
class Manager extends Leader {

public function __construct($name)
{
parent::__construct($name);
}

/**
* 经理批准三天以上十天以下的请假
* @param LeaveRequest $leaveRequest
*/
public function handleRequest(LeaveRequest $leaveRequest)
{
if ($leaveRequest->leaveDays <= 10) {
echo '请假人:'.$leaveRequest->empName.',天数:'.$leaveRequest->leaveDays.',理由:'.$leaveRequest->reason.PHP_EOL;
echo '审批人:'.$this->name.PHP_EOL;
} else {
if (!empty($this->nextLeader)) {
$this->nextLeader->handleRequest($leaveRequest);
}
}
}
}

/**
* 总经理
* Class GeneralManager
*/
class GeneralManager extends Leader {
public function __construct($name)
{
parent::__construct($name);
}

/**
* 总经理批准十天以上的请假
* @param LeaveRequest $leaveRequest
*/
public function handleRequest(LeaveRequest $leaveRequest)
{
echo '请假人'.$leaveRequest->empName.',天数:'.$leaveRequest->leaveDays.',理由:'.$leaveRequest->reason.PHP_EOL;
echo '审批人:'.$this->name.PHP_EOL;
}
}

class Client {
public function run()
{
// 构建责任链处理者
$director = new Director('主管');
$manager = new Manager('经理');
$generalManager = new GeneralManager('总经理');

// 设置各个责任链的关系
$director->setNextLeader($manager);
$manager->setNextLeader($generalManager);

// 请假
$request = new LeaveRequest('小明', 3, '旅游');
$director->handleRequest($request);

$request = new LeaveRequest('小红', 13, '看花灯');
$director->handleRequest($request);

$request = new LeaveRequest('小亮', 8, '看病');
$director->handleRequest($request);
}
}

$client = new Client();

$client->run();
1
2
3
4
5
6
请假人小明,天数:3,理由:旅游
审批人:主管
请假人小红,天数:13,理由:看花灯
审批人:总经理
请假人:小亮,天数:8,理由:看病
审批人:经理