Chain of Responsibility Pattern是一種行為型設計模式,目的是在多個對象間處理請求時,達到解耦與組織的效果。此模式將多個對象連接成一條鏈,每個對象都有機會處理請求。當一個對像不能處理請求時,會將請求轉發到下一個對象,直到能夠處理或到達鏈的末端。
舉例來說,有一個單位要向國家政府提出一個計畫,計畫分為四個階段:初步的方案、詳細的方案、執行的方案和結果的報告。每個階段的負責人負責處理相關的工作,如果負責人無法處理該階段的工作,則需要向下一個負責人傳遞請求,直到工作完成。
使用Chain of Responsibility Pattern可以有效地處理這個問題。我們可以將四個階段的負責人連接成一條鏈,每個負責人都有處理該階段工作的能力。如果一個負責人無法處理該階段的工作,他會將請求傳遞給下一個負責人,直到該階段的工作完成。
例如,初步的方案負責人無法處理詳細方案的工作,因此他將請求傳遞給詳細方案的負責人,如果詳細方案的負責人無法處理,他會轉發給執行方案的負責人,最終到達結果的報告負責人。此模式能夠減少耦合併更容易維護,因為每個負責人都可以獨立處理工作,而不必知道工作的詳細情況或其他負責人的工作。
Chain of Responsibility 模式是一種行為型設計模式,通過組合對像形成一條鏈,每個對象都能夠處理請求,若無法處理則傳遞給下一個對象。
可以通過該模式消除發送者和接收者之間的耦合關係,使得請求可以被多個對象處理。
Chain of Responsibility 模式應用於多個對象相互交互的場景,其中每個對象都可以根據需要動態處理請求,並且該模式能夠優雅地處理複雜的請求處理過程。
該模式的優點包括:增強代碼的復用性和靈活性,降低系統的耦合度,方便添加或刪除處理者等。
該模式的缺點包括:鏈條過長可能會降低性能,並且由於鏈條中的每個對象都可以執行處理,因此可能會導致請求被重複處理。
在實現該模式時,需要定義一個抽像處理類,該類包含一個處理請求的方法以及設置下一個處理者的方法。同時還需要實現各個對象的具體處理邏輯。
答案:請參考以下範例Code
答案:請參考以下範例Code
答案:請參考以下範例Code
答案:請參考以下範例Code
答案:請參考以下範例Code
以下是範例Code:
例一.
interface Worker
{
public function setNext(Worker $worker);
public function handle($car);
}
class Inspector implements Worker
{
private $nextWorker;
public function setNext(Worker $worker)
{
$this->nextWorker = $worker;
}
public function handle($car)
{
if ($car->getProblemLevel() == ‘minor’)
{
echo “Inspector handles the car by repairing the problem directly.\n”;
$car->setProblemFixed();
}
else
{
$this->nextWorker->handle($car);
}
}
}
class Mechanic implements Worker
{
private $nextWorker;
public function setNext(Worker $worker)
{
$this->nextWorker = $worker;
}
public function handle($car)
{
if ($car->getProblemLevel() == ‘moderate’)
{
echo “Mechanic handles the car by repairing the problem.\n”;
$car->setProblemFixed();
}
else
{
$this->nextWorker->handle($car);
}
}
}
class SeniorTechnician implements Worker
{
public function setNext(Worker $worker)
{
// This is the last class in the chain
}
public function handle($car)
{
if ($car->getProblemLevel() == ‘complex’)
{
echo “Senior technician handles the car by repairing the problem.\n”;
$car->setProblemFixed();
}
else
{
echo “Sorry, we are unable to repair the problem.\n”;
$car->setProblemUnfixed();
}
}
}
class Car
{
private $problemLevel;
private $problemFixed = false;
public function __construct($problemLevel)
{
$this->problemLevel = $problemLevel;
}
public function getProblemLevel()
{
return $this->problemLevel;
}
public function setProblemFixed()
{
$this->problemFixed = true;
}
public function setProblemUnfixed()
{
$this->problemFixed = false;
}
public function isFixed()
{
return $this->problemFixed;
}
}
?>
使用範例:
輸出結果:
Inspector handles the car by repairing the problem directly.
Is car1’s problem fixed? Yes.
Mechanic handles the car by repairing the problem.
Is car2’s problem fixed? Yes.
Senior technician handles the car by repairing the problem.
Is car3’s problem fixed? Yes.
例二.
interface Employee
{
public function setNext(Employee $employee);
public function work($food);
}
class Cashier implements Employee
{
private $nextEmployee;
public function setNext(Employee $employee)
{
$this->nextEmployee = $employee;
}
public function work($food)
{
echo “Cashier calculates the cost of the food.\n”;
$this->nextEmployee->work($food);
}
}
class Chef implements Employee
{
private $nextEmployee;
public function setNext(Employee $employee)
{
$this->nextEmployee = $employee;
}
public function work($food)
{
echo “Chef cooks the food according to the order.\n”;
$this->nextEmployee->work($food);
}
}
class Cleaner implements Employee
{
public function setNext(Employee $employee)
{
// This is the last class in the chain
}
public function work($food)
{
echo “Cleaner cleans up the table after the customer leaves.\n”;
}
}
?>
使用範例:
輸出結果:
Cashier calculates the cost of the food.
Chef cooks the food according to the order.
Cleaner cleans up the table after the customer leaves.
例三.
interface Employee
{
public function setNext(Employee $employee);
public function work($patient);
}
class Receptionist implements Employee
{
private $nextEmployee;
public function setNext(Employee $employee)
{
$this->nextEmployee = $employee;
}
public function work($patient)
{
echo “Receptionist asks for patient’s basic information.\n”;
$this->nextEmployee->work($patient);
}
}
class Doctor implements Employee
{
private $nextEmployee;
public function setNext(Employee $employee)
{
$this->nextEmployee = $employee;
}
public function work($patient)
{
if ($patient->isSerious())
{
echo “Doctor diagnoses and sends the patient to the operating room.\n”;
}
else
{
echo “Doctor diagnoses and prescribes medicine for the patient.\n”;
}
}
}
class Surgeon implements Employee
{
public function setNext(Employee $employee)
{
// This is the last class in the chain
}
public function work($patient)
{
echo “Surgeon performs the surgery on the patient.\n”;
}
}
class Patient
{
private $isSerious;
public function __construct($isSerious)
{
$this->isSerious = $isSerious;
}
public function isSerious()
{
return $this->isSerious;
}
}
?>
使用範例:
輸出結果:
Receptionist asks for patient’s basic information.
Doctor diagnoses and prescribes medicine for the patient.
Receptionist asks for patient’s basic information.
Doctor diagnoses and sends the patient to the operating room.
Surgeon performs the surgery on the patient.
例四.
interface Logger
{
public function setNext(Logger $logger);
public function log($level, $message);
}
class InformationLogger implements Logger
{
private $nextLogger;
public function setNext(Logger $logger)
{
$this->nextLogger = $logger;
}
public function log($level, $message)
{
if ($level == ‘information’)
{
echo “InformationLogger: $message\n”;
return true;
}
elseif (!is_null($this->nextLogger))
{
return $this->nextLogger->log($level, $message);
}
else
{
return false;
}
}
}
class WarningLogger implements Logger
{
private $nextLogger;
public function setNext(Logger $logger)
{
$this->nextLogger = $logger;
}
public function log($level, $message)
{
if ($level == ‘warning’)
{
echo “WarningLogger: $message\n”;
return true;
}
elseif (!is_null($this->nextLogger))
{
return $this->nextLogger->log($level, $message);
}
else
{
return false;
}
}
}
class ErrorLogger implements Logger
{
private $nextLogger;
public function setNext(Logger $logger)
{
$this->nextLogger = $logger;
}
public function log($level, $message)
{
if ($level == ’error’)
{
echo “ErrorLogger: $message\n”;
return true;
}
elseif (!is_null($this->nextLogger))
{
return $this->nextLogger->log($level, $message);
}
else
{
return false;
}
}
}
?>
使用範例:
輸出結果:
InformationLogger: The system is starting up.
WarningLogger: The system has encountered an error.
ErrorLogger: The system has crashed.
例五.
interface ReviewHandler
{
public function setNext(ReviewHandler $handler);
public function handle($comment);
}
class BasicReviewHandler implements ReviewHandler
{
private $nextHandler;
public function setNext(ReviewHandler $handler)
{
$this->nextHandler = $handler;
}
public function handle($comment)
{
if ($comment->getLevel() == ‘basic’)
{
echo “Basic review is displayed directly.\n”;
}
elseif (!is_null($this->nextHandler))
{
$this->nextHandler->handle($comment);
}
else
{
echo “Sorry, your comment cannot be displayed.\n”;
}
}
}
class CertifiedReviewHandler implements ReviewHandler
{
private $nextHandler;
public function setNext(ReviewHandler $handler)
{
$this->nextHandler = $handler;
}
public function handle($comment)
{
if ($comment->getLevel() == ‘certified’)
{
echo “Certified review has to be approved before being displayed.\n”;
}
elseif (!is_null($this->nextHandler))
{
$this->nextHandler->handle($comment);
}
else
{
echo “Sorry, your comment cannot be displayed.\n”;
}
}
}
class ProReviewHandler implements ReviewHandler
{
private $nextHandler;
public function setNext(ReviewHandler $handler)
{
$this->nextHandler = $handler;
}
public function handle($comment)
{
if ($comment->getLevel() == ‘pro’)
{
echo “Pro review is sent to a specialist for reply.\n”;
}
elseif (!is_null($this->nextHandler))
{
$this->nextHandler->handle($comment);
}
else
{
echo “Sorry, your comment cannot be displayed.\n”;
}
}
}
class Comment
{
private $level;
public function __construct($level)
{
$this->level = $level;
}
public function getLevel()
{
return $this->level;
}
}
?>
使用範例:
輸出結果:
Basic review is displayed directly.
Certified review has to be approved before being displayed.
Pro review is sent to a specialist for reply.