[toc]
## 舉個例子
> 如需請假, 根據天數的不同, 需要請示不同的領導
1. 小于等于2天,直屬領導簽字,提交行政部門;
2. 大于2天,小于等于5天,直屬領導簽字,部門總監簽字,提交行政部門;
3. 大于5天,小于等于1月,直屬領導簽字,部門總監簽字,CEO 簽字,提交行政部門。
## 代碼示例
```php
<?php
// 請求內容
class Request {
private $name;
private $dayoff;
private $reason;
private $leader;
public function __construct($name, $dayoff, $reason) {
$this->name = $name;
$this->dayoff = $dayoff;
$this->reason = $reason;
$this->leader = null;
}
public function getName() {
return $this->name;
}
public function getDayOff() {
return $this->dayoff;
}
public function getReason() {
return $this->reason;
}
}
// 責任人的抽象類
class Responsible {
private $name;
private $title;
private $nextHandler;
public function __init__($name, $title) {
$this->name = $name;
$this->title = $title;
$this->nextHandler = null;
}
public function getName() {
return $this->name;
}
public function getTitle() {
return $this->title;
}
public function setNextHandler($nextHandler) {
$this->nextHandler = $nextHandler;
}
public function getNextHandler() {
return $this->nextHandler;
}
public function handleRequest($request) {
}
}
// 請求者
class Person {
private $name;
private $leader;
public function __construct($name) {
$this->name = $name;
$this->leader = null;
}
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function setLeader($leader) {
$this->leader = $leader;
}
public function getLeader() {
return $this->leader;
}
public function sendReuqest($request) {
echo $this->name . "申請請假" . $request->getDayOff() . "天。請假事由:" . $request->getReason();
if ($this->leader) {
$this->leader->handleRequest($request);
}
}
}
// 主管
class Supervisor extends Responsible {
public function __construct($name, $title) {
parent::__init__($name, $title);
}
public function handleRequest($request) {
if ($request->getDayOff() <= 2) {
echo "同意 " . $request->getName() . " 請假,簽字人:" . $this->getName() . "(" . $this->getTitle() . ")" . PHP_EOL;
}
$nextHandler = $this->getNextHandler();
if ($nextHandler) {
$nextHandler->handleRequest($request);
}
}
}
// 部門總監
class DepartmentManager extends Responsible {
public function __construct($name, $title) {
parent::__init__($name, $title);
}
public function handleRequest($request) {
if ($request->getDayOff() > 2 and $request->getDayOff() <= 5) {
echo "同意 " . $request->getName() . " 請假,簽字人:" . $this->getName() . "(" . $this->getTitle() . ")" . PHP_EOL;
}
$nextHandler = $this->getNextHandler();
if ($nextHandler) {
$nextHandler->handleRequest($request);
}
}
}
// CEO
class CEO extends Responsible {
public function __construct($name, $title) {
parent::__init__($name, $title);
}
public function handleRequest($request) {
if ($request->getDayOff() > 5 and $request->getDayOff() <= 22) {
echo "同意 " . $request->getName() . " 請假,簽字人:" . $this->getName() . "(" . $this->getTitle() . ")" . PHP_EOL;
}
$nextHandler = $this->getNextHandler();
if ($nextHandler) {
$nextHandler->handleRequest($request);
}
}
}
// 行政人員
class Administrator extends Responsible {
public function __construct($name, $title) {
parent::__init__($name, $title);
}
public function handleRequest($request) {
echo $request->getName() . "的請假申請已審核,情況屬實!已備案處理。處理人:" . $this->getName() . "(" . $this->getTitle() . ")\n";
$nextHandler = $this->getNextHandler();
}
}
// 測試
function test() {
$directLeader = new Supervisor("Eren", "客戶端研發部經理");
$departmentLeader = new DepartmentManager("Eric", "技術研發中心總監");
$ceo = new CEO("Helen", "創新文化公司CEO");
$administrator = new Administrator("Nina", "行政中心總監");
$directLeader->setNextHandler($departmentLeader);
$departmentLeader->setNextHandler($ceo);
$ceo->setNextHandler($administrator);
$sunny = new Person("Sunny");
$sunny->setLeader($directLeader);
$sunny->sendReuqest(new Request($sunny->getName(), 1, "參加MDCC大會。"));
$tony = new Person("Tony");
$tony->setLeader($directLeader);
$tony->sendReuqest(new Request($tony->getName(), 5, "家里有緊急事情!"));
$pony = new Person("Pony");
$pony->setLeader($directLeader);
$pony->sendReuqest(new Request($pony->getName(), 15, "出國深造。"));
}
test();
```
```
D:\soft\php72\php.exe D:\project\php_dp\index.php
Sunny申請請假1天。請假事由:參加MDCC大會。同意 Sunny 請假,簽字人:Eren(客戶端研發部經理)
Sunny的請假申請已審核,情況屬實!已備案處理。處理人:Nina(行政中心總監)
Tony申請請假5天。請假事由:家里有緊急事情!同意 Tony 請假,簽字人:Eric(技術研發中心總監)
Tony的請假申請已審核,情況屬實!已備案處理。處理人:Nina(行政中心總監)
Pony申請請假15天。請假事由:出國深造。同意 Pony 請假,簽字人:Helen(創新文化公司CEO)
Pony的請假申請已審核,情況屬實!已備案處理。處理人:Nina(行政中心總監)
Process finished with exit code 0
```
## 代碼說明
> 你只需要填寫`姓名`,`請假天數`, `請假理由`給行政即可, 至于應該讓誰簽字, 讓管理層自己去判斷, 如果權限不足, 就依次上報.


## 什么是職責模式?
> 避免請求發送者與接收者耦合在一起,讓多個對象都有可能接收請求,將這些對象連接成一條鏈,并且沿著這條鏈傳遞請求,直到有對象處理它為止。職責模式也稱為責任鏈模式,它是一種對象行為型模式。
> 職責鏈模式將請求的發送者和接受者解耦了。客戶端不需要知道請求處理者的明確信息和處理的具體邏輯,甚至不需要知道鏈的結構,它只需要將請求進行發送即可。
## 設計要點
1. **請求者與請求內容**:誰要發送請求?發送請求的對象稱為請求者。請求的內容通過發送請求時的參數進行傳遞。
1. **有哪些責任人**:責任人是構成責任鏈的關鍵要素。請求的流動方向是鏈條中的線,而責任人則是鏈條上的結點,線和結點才構成了一條鏈條。
1. **對責任人進行抽象**:真實世界中的責任人會多種多樣,紛繁復雜,會有不同的職責和功能;但他們也有一個共同的特征——都可以處理請求。所以需要對責任人進行抽象,使他們具有責任的可傳遞性。
1. **責任人可自由組合**:責任鏈上的責任人可以根據業務的具體邏輯進行自由的組合和排序。
## 模式的優缺點
**優點**:
* 降低耦合度。它將請求的發送者和接受者解耦。
* 簡化了對象。使得對象不需要知道鏈的結構。
* 增強給對象指派職責的靈活性。通過改變鏈內的成員或者調動它們的次序,允許動態地新增或者刪除責任人。
* 增加新的處理類很方便。
**職責模式的缺點**:
* 不能保證請求一定被接收。
* 系統性能將受到一定影響,而且在進行代碼調試時不太方便,可能會造成循環調用。
## 應用場景
1. 有多個對象可以處理同一個請求,具體哪個對象處理該請求由運行時刻自動確定。
1. 請求的處理具有明顯的一層層傳遞關系。
1. 請求的處理流程和順序需要程序運行時動態確定。