7、職責鏈模式 (Chainof Responsibility):
多個物件有機會處理請求,為請求發送者和接收者解耦。就像銀行裡的提款機,不管那一台都可以拿錢。
好處:簡化物件隱藏鏈結結構,方便新增職責節點。
弊端:請求可能沒有接受者,或被多個接收者調用,效能降低。
應用場景:處理多種請求。
程式碼實作:
<?php /** * 优才网公开课示例代码 * * 职责链模式 Chain of Responsibility * * @author 优才网全栈工程师教研组 * @see http://www.ucai.cn */ function output($string) { echo $string . "\n"; } /** * 加入在公司里,如果你的请假时间小于0.5天,那么只需要向leader打声招呼就OK了。 如果0.5<=请假天数<=3天,需要先leader打声招呼,然后部门经理签字。 如果3<请假天数,需要先leader打声招呼,然后到部门经理签字,最后总经经理确认签字, 如果请假天数超过10天,是任何人都不能批准的。 */ /** * 抽象处理者角色(Handler:Approver):定义一个处理请求的接口,和一个后继连接(可选) * */ abstract class Handler { protected $_handler = null; protected $_handlerName = null; public function setSuccessor($handler) { $this->_handler = $handler; } protected function _success($request) { output(sprintf("%s's request was passed", $request->getName())); return true; } abstract function handleRequest($request); } /** * 具体处理者角色(ConcreteHandler:President):处理它所负责的请求,可以访问后继者,如果可以处理请求则处理,否则将该请求转给他的后继者。 * */ class ConcreteHandlerLeader extends Handler { function __construct($handlerName){ $this->_handlerName = $handlerName; } public function handleRequest($request) { if($request->getDay() < 0.5) { output(sprintf('%s was told', $this->_handlerName)); // 已经跟leader招呼了 return $this->_success($request); } if ($this->_handler instanceof Handler) { return $this->_handler->handleRequest($request); } } } /** * Manager * */ class ConcreteHandlerManager extends Handler { function __construct($handlerName){ $this->_handlerName = $handlerName; } public function handleRequest($request) { if(0.5 <= $request->getDay() && $request->getDay()<=3) { output(sprintf('%s signed', $this->_handlerName)); // 部门经理签字 return $this->_success($request); } if ($this->_handler instanceof Handler) { return $this->_handler->handleRequest($request); } } } class ConcreteHandlerGeneralManager extends Handler { function __construct($handlerName){ $this->_handlerName = $handlerName; } public function handleRequest($request) { if(3 < $request->getDay() && $request->getDay() < 10){ output(sprintf('%s signed', $this->_handlerName)); // 总经理签字 return $this->_success($request); } if ($this->_handler instanceof Handler) { return $this->_handler->handleRequest($request); } else { output(sprintf('no one can approve request more than 10 days')); } } } /** * 请假申请 * */ class Request { private $_name; private $_day; private $_reason; function __construct($name= '', $day= 0, $reason = ''){ $this->_name = $name; $this->_day = $day; $this->_reason = $reason; } public function setName($name){ $this->_name = $name; } public function getName(){ return $this->_name; } public function setDay($day){ $this->_day = $day; } public function getDay(){ return $this->_day ; } public function setReason($reason ){ $this->_reason = $reason; } public function getReason( ){ return $this->_reason; } } class Client { public static function test(){ $leader = new ConcreteHandlerLeader('leader'); $manager = new ConcreteHandlerManager('manager'); $generalManager = new ConcreteHandlerGeneralManager('generalManager'); //请求实例 $request = new Request('ucai',4,'休息'); $leader->setSuccessor($manager); $manager->setSuccessor($generalManager); $result = $leader->handleRequest($request); } } Client::test();
8、策略模式(Strategy):
定義一系列演算法,將每一個演算法封裝起來,並且使它們可互相取代。就像籃球隊裡的球員,場上的和場下休息的。教練可以讓場上的下來,也可以讓場下的上陣。
好處:定義可重複使用的一系列演算法和行為,並且消除了if else語句。
弊端:呼叫端必須知道所有策略類別。
應用場景:用於物件間的替換。
程式碼實作:
<?php /** * 优才网公开课示例代码 * * 策略模式 Strategy * * @author 优才网全栈工程师教研组 * @see http://www.ucai.cn */ function output($string) { echo $string . "\n"; } //策略基类接口 interface IStrategy { public function OnTheWay(); } class WalkStrategy implements IStrategy { public function OnTheWay() { output( '在路上步行'); } } class RideBickStrategy implements IStrategy { public function OnTheWay() { output( '在路上骑自行车'); } } class CarStrategy implements IStrategy { public function OnTheWay() { output( '在路上开车'); } } //选择策略类Context class Context { public function find($strategy) { $strategy->OnTheWay(); } } class Client { public static function test(){ $travel = new Context(); $travel->find(new WalkStrategy()); $travel->find(new RideBickStrategy()); $travel->find(new CarStrategy()); } } Client::test();
已知模式
1、備忘錄模式(Memento):
保存物件在瞬間的狀態。親,還記得「老師來了記得叫我一下」的同桌的他嗎?
好處:提供使用者了一種可以恢復狀態的機制。
弊端:消耗資源。
應用場景:用於需要儲存的資料。
程式碼實作:
<?php /** * 优才网公开课示例代码 * * 备忘录模式 Memento * * @author 优才网全栈工程师教研组 * @see http://www.ucai.cn */ function output($string) { echo $string . "\n"; } class Originator { // 发起人(Originator)角色 private $_state; public function __construct() { $this->_state = ''; } public function createMemento() { // 创建备忘录 return new Memento($this->_state); } public function restoreMemento(Memento $memento) { // 将发起人恢复到备忘录对象记录的状态上 $this->_state = $memento->getState(); } public function setState($state) { $this->_state = $state; } public function getState() { return $this->_state; } public function showState() { output($this->_state); } } class Memento { // 备忘录(Memento)角色 private $_state; public function __construct($state) { $this->setState($state); } public function getState() { return $this->_state; } public function setState($state) { $this->_state = $state;} } class Caretaker { // 负责人(Caretaker)角色 private $_memento; public function getMemento() { return $this->_memento; } public function setMemento(Memento $memento) { $this->_memento = $memento; } } class Client { public static function test(){ $org = new Originator(); $org->setState('open'); $org->showState(); /* 创建备忘 */ $memento = $org->createMemento(); /* 通过Caretaker保存此备忘 */ $caretaker = new Caretaker(); $caretaker->setMemento($memento); /* 改变目标对象的状态 */ $org->setState('close'); $org->showState(); /* 还原操作 */ $org->restoreMemento($caretaker->getMemento()); $org->showState(); } } Client::test(); return; try { $db->beginTransaction(); $succ = $db->exec($sql_1); if (!$succ) { throw new Exception('SQL 1 update failed'); } $succ = $db->exec($sql_2); if (!$succ) { throw new Exception('SQL 2 update failed'); } $succ = $db->exec($sql_3); if (!$succ) { throw new Exception('SQL 3 update failed'); } $db->commit(); } catch (Exception $exp) { $db->rollBack(); }
深度模式
1、解釋器模式(Interpreter):
定義語言的文法,並建立一個解釋器來解釋該語言中的句子。每個用過字典的童鞋都懂滴。
好處:可擴充性較佳,且彈性高。
弊端:可能難以維持複雜的文法。
應用場景:用於成對或一對多的需求中。
2、訪客模式(Visitor):
封裝某些用於作用於某種資料結構中各元素的操作,可在不改變資料結構的前提下定義作用於這些元素的新操作。如銀行排號機。
好處:將相關的事物集中到一個訪客物件中。
弊端:增加新資料結構很困難。
應用場景:排隊,排號。
三、總結
本篇介紹了行為型模式,行為模式涉及到演算法和物件職責模式之間的分配,而行為類別模式採用繼承機制在類別間分派行為,TemplateMethod行為和preter 。行為物件模式使用物件複合而不是繼承,一些行為物件模式描述了一組相互對等的物件如何相互協作以完成其中任何一個物件都單獨無法完成的任務,如Mediator在物件之間引入一個mediator物件提供了松耦合所需的間接性;Chain of Responsibility提供了更鬆的耦合,它透過一條候選物件鏈隱式的向一個物件發松請求,可以運行時刻決定哪些候選者參與到鏈中;Observer定義並保持了物件間的依賴關係;其它的行為物件模式常將行為封裝在一個物件中,並將請求指派給它,Strategy模式將演算法封裝在物件中,這樣可以方面的改變和指定一個物件所使用的演算法;Command模式將請求封裝在物件中,這樣它就可以作為參數來傳遞,已可以儲存在歷史清單中或以其它方式使用;State模式封裝一個物件的狀態,使得當這個物件的狀態物件發生變化時,該物件可改變它的行為;Visitor模式封裝分佈於多個類別之間的行為;而Iterator模式則抽象化了存取和遍歷一個集合中物件的方式。