責任鏈模式 Chain Of Responsibilities
顧名思義,責任鏈模式(Chain of Responsibility Pattern)為請求建立了一個接收者物件的鏈。這種模式給予請求的型別,對請求的傳送者和接收者進
行解耦。這種型別的設計模式屬於行為型模式。在這種模式中,通常每個接收者都包含對另一個接收者的引用。如果一個物件不能處理該請求,那麼它會把相同的
請求傳給下一個接收者,依此類推。
責任鏈模式也是屬於行為型模式
責任鏈模式是有一個請求類,一個請求處理者抽象類,然後有多個請求處理者字類去處理請求
比如現在有一個場景,有一個學校,學校平時需要採購一些物品,比如粉筆,黑板擦,垃圾桶,掃帚,大一點的物品,智慧課堂的電子裝置,學生桌椅的報修,
周圍環境的裝修呀,老師的備課用品呀等等,一些小的物品,比如3000元一下的,可能一個管後勤的小科員就可以直接簽字同意,一些3000-4500元的物品,就
需要主任來簽字同意了,再大一點的4500-10000就需要副校長簽字同意了,那麼再大一點10000-50000的就需要校長來簽字了,大於50000的就需要教育局來
報備了,就不是學校可以自行決定的了。根據3的物理場景,就可以使用職責鏈模式了,購買物品就是一個請求,需要對應的請求處理者(小科員,主任,副校長,校長)來處理。
比如請求處理,可以定義一個請求類,
Request
,可以把請求類做成一個介面,然後去實現它,這裡只是做實驗,就只作一個類,不去些介面了
class Request
{
public $id = 0;
public $price = 0;
public $type = 1;
public $desc = '';
public function __construct(int $id = 0, int $price = 0, int $type = 1, string $desc = '')
{
$this->id = $id;
$this->price = $price;
$this->type = $type;
$this->desc = $desc;
}
public function getId()
{
return $this->id;
}
public function getType()
{
return $this->type;
}
public function getPrice()
{
return $this->price;
}
public function getDesc()
{
return $this->desc;
}
}
- 定義一個請求處理抽象類,這個抽象類定義三個方法,一個是
__construct(Request $request)
,它接受一個請求類Request
,
第二個方法是final public function requestHandle(RequestHandleAbstract $abstract)
,它會接受一個自身的抽象類引數,把當前處理者處理
不了的問題,指向下一個處理者,第三個方法就是當前的處理者的具體操作abstract public function processHandle();
它是一個抽象方法
abstract class RequestHandleAbstract
{
protected $request;
public function __construct(Request $request)
{
$this->request = $request;
}
/**
* Notes:指向下一個請求
* Name: requestHandle
* User: LiYi
* Date: 2020/6/16
* Time: 22:20
* @param RequestHandleAbstract $abstract
* @return mixed
*/
final public function requestHandle(RequestHandleAbstract $abstract)
{
$abstract->processHandle();
}
/**
* Notes:具體的處理請求程式
* Name: processHandle
* User: LiYi
* Date: 2020/6/16
* Time: 22:21
* @return mixed
*/
abstract public function processHandle();
}
- 分別定義科員,主任,父校長,校長的處理請求的具體實現類
class ClerkSchool extends RequestHandleAbstract
{
public function processHandle()
{
// TODO: Implement processHandle() method.
if ($this->request->getPrice() <= 3000) {
echo '此次請求的任務是: '.$this->request->getDesc() . ' 請求的id是:' . $this->request->getId() . ' 請求的型別是:'
. $this->request->getType() . ' 此次批覆的金額為:' . $this->request->getPrice(). PHP_EOL;
echo '處理人是科員' . PHP_EOL;
} else {
$this->requestHandle(new DirectorSchool($this->request));
}
}
}
class DirectorSchool extends RequestHandleAbstract
{
public function processHandle()
{
// TODO: Implement processHandle() method.
if ($this->request->getPrice() > 3000 && $this->request->getPrice() <= 4500) {
echo '此次請求的任務是: '.$this->request->getDesc() . ' 請求的id是:' . $this->request->getId() . ' 請求的型別是:'
. $this->request->getType() . ' 此次批覆的金額為:' . $this->request->getPrice(). PHP_EOL;
echo '處理人是主任' . PHP_EOL;
} else {
$this->requestHandle(new VicePrincipalSchool($this->request));
}
}
}
class VicePrincipalSchool extends RequestHandleAbstract
{
public function processHandle()
{
// TODO: Implement processHandle() method.
if ($this->request->getPrice() > 4500 && $this->request->getPrice() <= 10000) {
echo '此次請求的任務是: '.$this->request->getDesc() . ' 請求的id是:' . $this->request->getId() . ' 請求的型別是:'
. $this->request->getType() . ' 此次批覆的金額為:' . $this->request->getPrice(). PHP_EOL;
echo '處理人是副校長' . PHP_EOL;
} else {
$this->requestHandle(new PrincipalSchool($this->request));
}
}
}
class PrincipalSchool extends RequestHandleAbstract
{
public function processHandle()
{
// TODO: Implement processHandle() method.
// TODO: Implement processHandle() method.
if ($this->request->getPrice() > 10000 && $this->request->getPrice() <= 50000) {
echo '此次請求的任務是: '.$this->request->getDesc() . ' 請求的id是:' . $this->request->getId() . ' 請求的型別是:'
. $this->request->getType() . ' 此次批覆的金額為:' . $this->request->getPrice(). PHP_EOL;
echo '處理人是校長' . PHP_EOL;
} else {
echo '超出職責範圍處理不了' . PHP_EOL;
}
}
}
- 測試,我們使用隨機的需要採購物品的價格,來測試,看看不同的價格,最後是不是按照我們的想法得到處理的
class Client
{
public function __construct()
{
$request = new Request(mt_rand(1111, 9999), mt_rand(1, 99999), mt_rand(1, 9), '學校裝修新電子教室');
$clerk = new ClerkSchool($request);
$clerk->processHandle();
}
}
require '../vendor/autoload.php';
new Client();
本作品採用《CC 協議》,轉載必須註明作者和本文連結
LIYi ---- github地址