您好,登錄后才能下訂單哦!
<接上一篇>
5、中介者模式(Mediator):
用中介對象封裝一系列的對象交互,中介使各對象不需要顯式地相互引用。類似于郵局,郵寄者和收件者不用自己跑很遠路,通過郵局就可以。
好處:簡化了對象之間的關系,減少子類的生成
弊端:中介對象可能變得非常復雜,系統難以維護
應用場景:不需要顯示地建立交互
代碼實現:
<?php /** * 優才網公開課示例代碼 * * 中介者模式 Mediator * * @author 優才網全棧工程師教研組 * @seehttp://www.ucai.cn */ function output($string) { echo $string . "\n"; } abstract class Mediator { // 中介者角色 abstractpublic function send($message,$colleague); } abstract class Colleague { // 抽象對象 private$_mediator = null; publicfunction __construct($mediator) { $this->_mediator = $mediator; } publicfunction send($message) { $this->_mediator->send($message,$this); } abstractpublic function notify($message); } class ConcreteMediator extends Mediator { // 具體中介者角色 private$_colleague1 = null; private$_colleague2 = null; publicfunction send($message,$colleague) { if($colleague == $this->_colleague1) { $this->_colleague1->notify($message); } else{ $this->_colleague2->notify($message); } } publicfunction set($colleague1,$colleague2) { $this->_colleague1 = $colleague1; $this->_colleague2 = $colleague2; } } class Colleague1 extends Colleague { // 具體對象角色 publicfunction notify($message) { output(sprintf('Colleague-1: %s', $message)); } } class Colleague2 extends Colleague { // 具體對象角色 publicfunction notify($message) { output(sprintf('Colleague-2: %s', $message)); } } class Client { publicstatic function test(){ //client $objMediator = new ConcreteMediator(); $objC1= new Colleague1($objMediator); $objC2= new Colleague2($objMediator); $objMediator->set($objC1,$objC2); $objC1->send("to c2 from c1"); $objC2->send("to c1 from c2"); } } Client::test();
6、狀態模式(State) :
對象在不同狀態下表現出不同的行為。就像女朋友一樣,高興了牽你的手,不高興了遛狗。在兩種狀態下變現出不同的行為。
好處:避免if語句實用,方便增加新狀態,封裝了狀態轉換規則。
弊端:增加系統類和對象的數量。
應用場景:用于對象的不同功能的轉換。
代碼實現:
<?php /** * 優才網公開課示例代碼 * * 狀態模式 State * * @author 優才網全棧工程師教研組 * @see http://www.ucai.cn */ function output($string) { echo $string . "\n"; } abstract class ILift { //電梯的四個狀態 constOPENING_STATE = 1; //門敞狀態 constCLOSING_STATE = 2; //門閉狀態 constRUNNING_STATE = 3; //運行狀態 constSTOPPING_STATE = 4; //停止狀態; //設置電梯的狀態 publicabstract function setState($state); //首先電梯門開啟動作 publicabstract function open(); //電梯門有開啟,那當然也就有關閉了 publicabstract function close(); //電梯要能上能下,跑起來 publicabstract function run(); //電梯還要能停下來 publicabstract function stop(); } /** * 電梯的實現類 */ class Lift extends ILift { private$state; publicfunction setState($state) { $this->state = $state; } //電梯門關閉 publicfunction close() { //電梯在什么狀態下才能關閉 switch($this->state) { case ILift::OPENING_STATE: //如果是則可以關門,同時修改電梯狀態 $this->setState(ILift::CLOSING_STATE); break; case ILift::CLOSING_STATE: //如果電梯就是關門狀態,則什么都不做 //do nothing; return ; break; case ILift::RUNNING_STATE: //如果是正在運行,門本來就是關閉的,也說明都不做 //do nothing; return ; break; case ILift::STOPPING_STATE: //如果是停止狀態,本也是關閉的,什么也不做 //do nothing; return ; break; } output('Lift colse'); } //電梯門開啟 publicfunction open() { //電梯在什么狀態才能開啟 switch($this->state){ case ILift::OPENING_STATE: //如果已經在門敞狀態,則什么都不做 //do nothing; return ; break; case ILift::CLOSING_STATE: //如是電梯時關閉狀態,則可以開啟 $this->setState(ILift::OPENING_STATE); break; case ILift::RUNNING_STATE: //正在運行狀態,則不能開門,什么都不做 //do nothing; return ; break; case ILift::STOPPING_STATE: //停止狀態,淡然要開門了 $this->setState(ILift::OPENING_STATE); break; } output('Lift open'); } ///電梯開始跑起來 publicfunction run() { switch($this->state){ case ILift::OPENING_STATE: //如果已經在門敞狀態,則不你能運行,什么都不做 //do nothing; return ; break; case ILift::CLOSING_STATE: //如是電梯時關閉狀態,則可以運行 $this->setState(ILift::RUNNING_STATE); break; case ILift::RUNNING_STATE: //正在運行狀態,則什么都不做 //do nothing; return ; break; case ILift::STOPPING_STATE: //停止狀態,可以運行 $this->setState(ILift::RUNNING_STATE); } output('Lift run'); } //電梯停止 publicfunction stop() { switch($this->state){ case ILift::OPENING_STATE: //如果已經在門敞狀態,那肯定要先停下來的,什么都不做 //do nothing; return ; break; case ILift::CLOSING_STATE: //如是電梯時關閉狀態,則當然可以停止了 $this->setState(ILift::CLOSING_STATE); break; case ILift::RUNNING_STATE: //正在運行狀態,有運行當然那也就有停止了 $this->setState(ILift::CLOSING_STATE); break; case ILift::STOPPING_STATE: //停止狀態,什么都不做 //do nothing; return ; break; } output('Lift stop'); } } class Client { publicstatic function test() { $lift= new Lift(); //電梯的初始條件應該是停止狀態 $lift->setState(ILift::STOPPING_STATE); //首先是電梯門開啟,人進去 $lift->open(); //然后電梯門關閉 $lift->close(); //再然后,電梯跑起來,向上或者向下 $lift->run(); //最后到達目的地,電梯挺下來 $lift->stop(); } } Client::test();
<?php /** * 優才網公開課示例代碼 * * 狀態模式 State * * @author 優才網全棧工程師教研組 * @seehttp://www.ucai.cn */ function output($string) { echo $string . "\n"; } /** * * 定義一個電梯的接口 */ abstract class LiftState{ //定義一個環境角色,也就是封裝狀態的變換引起的功能變化 protected $_context; publicfunction setContext(Context $context){ $this->_context = $context; } //首先電梯門開啟動作 publicabstract function open(); //電梯門有開啟,那當然也就有關閉了 publicabstract function close(); //電梯要能上能下,跑起來 publicabstract function run(); //電梯還要能停下來,停不下來那就扯淡了 publicabstract function stop(); } /** * 環境類:定義客戶感興趣的接口。維護一個ConcreteState子類的實例,這個實例定義當前狀態。 */ class Context { //定義出所有的電梯狀態 static $openningState =null; static $closeingState =null; static $runningState = null; static $stoppingState =null; publicfunction __construct() { self::$openningState = new OpenningState(); self::$closeingState = new ClosingState(); self::$runningState = new RunningState(); self::$stoppingState = new StoppingState(); } //定一個當前電梯狀態 private $_liftState; publicfunction getLiftState() { return$this->_liftState; } publicfunction setLiftState($liftState) { $this->_liftState = $liftState; //把當前的環境通知到各個實現類中 $this->_liftState->setContext($this); } publicfunction open(){ $this->_liftState->open(); } publicfunction close(){ $this->_liftState->close(); } publicfunction run(){ $this->_liftState->run(); } publicfunction stop(){ $this->_liftState->stop(); } } /** * 在電梯門開啟的狀態下能做什么事情 */ class OpenningState extends LiftState { /** * 開啟當然可以關閉了,我就想測試一下電梯門開關功能 * */ publicfunction close() { //狀態修改 $this->_context->setLiftState(Context::$closeingState); //動作委托為CloseState來執行 $this->_context->getLiftState()->close(); } //打開電梯門 publicfunction open() { output('lift open...'); } //門開著電梯就想跑,這電梯,嚇死你! publicfunction run() { //donothing; } //開門還不停止? publicfunction stop() { //donothing; } } /** * 電梯門關閉以后,電梯可以做哪些事情 */ class ClosingState extends LiftState { //電梯門關閉,這是關閉狀態要實現的動作 publicfunction close() { output('lift close...'); } //電梯門關了再打開,逗你玩呢,那這個允許呀 publicfunction open() { $this->_context->setLiftState(Context::$openningState); //置為門敞狀態 $this->_context->getLiftState()->open(); } //電梯門關了就跑,這是再正常不過了 publicfunction run() { $this->_context->setLiftState(Context::$runningState); //設置為運行狀態; $this->_context->getLiftState()->run(); } //電梯門關著,我就不按樓層 publicfunction stop() { $this->_context->setLiftState(Context::$stoppingState); //設置為停止狀態; $this->_context->getLiftState()->stop(); } } /** * 電梯在運行狀態下能做哪些動作 */ class RunningState extends LiftState { //電梯門關閉?這是肯定了 publicfunction close() { //donothing } //運行的時候開電梯門?你瘋了!電梯不會給你開的 publicfunction open() { //donothing } //這是在運行狀態下要實現的方法 publicfunction run() { output('lift run...'); } //這個事絕對是合理的,光運行不停止還有誰敢做這個電梯?!估計只有上帝了 publicfunction stop() { $this->_context->setLiftState(Context::$stoppingState); //環境設置為停止狀態; $this->_context->getLiftState()->stop(); } } /** * 在停止狀態下能做什么事情 */ class StoppingState extends LiftState { //停止狀態關門?電梯門本來就是關著的! publicfunction close() { //donothing; } //停止狀態,開門,那是要的! publicfunction open() { $this->_context->setLiftState(Context::$openningState); $this->_context->getLiftState()->open(); } //停止狀態再跑起來,正常的很 publicfunction run() { $this->_context->setLiftState(Context::$runningState); $this->_context->getLiftState()->run(); } //停止狀態是怎么發生的呢?當然是停止方法執行了 publicfunction stop() { output('lift stop...'); } } /** * 模擬電梯的動作 */ class Client { publicstatic function test() { $context = new Context(); $context->setLiftState(new ClosingState()); $context->open(); $context->close(); $context->run(); $context->stop(); } } Client::test();
7、職責鏈模式 (Chainof Responsibility):
多個對象有機會處理請求,為請求發送者和接收者解耦。就像銀行里的取款機,不管那一臺都可以取到錢。
好處:簡單化對象隱藏鏈結構,便于添加新職責節點
弊端:請求可能沒有接受者,或者被多個接收者調用,性能降低
應用場景:處理多種請求
代碼實現:
<?php /** * 優才網公開課示例代碼 * * 職責鏈模式 Chain of Responsibility * * @author 優才網全棧工程師教研組 * @seehttp://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; publicfunction setSuccessor($handler) { $this->_handler = $handler; } protected function_success($request) { output(sprintf("%s's request was passed",$request->getName())); returntrue; } abstractfunction handleRequest($request); } /** * 具體處理者角色(ConcreteHandler:President):處理它所負責的請求,可以訪問后繼者,如果可以處理請求則處理,否則將該請求轉給他的后繼者。 * */ class ConcreteHandlerLeader extends Handler { function__construct($handlerName){ $this->_handlerName = $handlerName; } publicfunction 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; } publicfunction 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 extendsHandler { function__construct($handlerName){ $this->_handlerName = $handlerName; } publicfunction 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; } publicfunction setName($name){ $this->_name = $name; } publicfunction getName(){ return $this->_name; } publicfunction setDay($day){ $this->_day = $day; } publicfunction getDay(){ return $this->_day ; } publicfunction setReason($reason ){ $this->_reason = $reason; } publicfunction getReason( ){ return $this->_reason; } } class Client { publicstatic function test(){ $leader= new ConcreteHandlerLeader('leader'); $manager = new ConcreteHandlerManager('manager'); $generalManager = newConcreteHandlerGeneralManager('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 優才網全棧工程師教研組 * @seehttp://www.ucai.cn */ function output($string) { echo $string . "\n"; } //策略基類接口 interface IStrategy { publicfunction OnTheWay(); } class WalkStrategy implements IStrategy { publicfunction OnTheWay() { output( '在路上步行'); } } class RideBickStrategy implements IStrategy { publicfunction OnTheWay() { output( '在路上騎自行車'); } } class CarStrategy implements IStrategy { publicfunction OnTheWay() { output( '在路上開車'); } } //選擇策略類Context class Context { public functionfind($strategy) { $strategy->OnTheWay(); } } class Client { publicstatic function test(){ $travel = new Context(); $travel->find(new WalkStrategy()); $travel->find(new RideBickStrategy()); $travel->find(new CarStrategy()); } } Client::test();
已知模式
1、備忘錄模式(Memento):
保存對象在一時刻的狀態。親,還記得“老師來了記得叫我一下”的同桌的他嗎?
好處:給用戶提供了一種可以恢復狀態的機制
弊端:消耗資源
應用場景:用于需要保存的數據
代碼實現:
<?php /** * 優才網公開課示例代碼 * * 備忘錄模式 Memento * * @author 優才網全棧工程師教研組 * @seehttp://www.ucai.cn */ function output($string) { echo $string . "\n"; } class Originator { // 發起人(Originator)角色 private$_state; publicfunction __construct() { $this->_state = ''; } publicfunction createMemento() { // 創建備忘錄 returnnew Memento($this->_state); } publicfunction restoreMemento(Memento $memento) { // 將發起人恢復到備忘錄對象記錄的狀態上 $this->_state = $memento->getState(); } publicfunction setState($state) { $this->_state = $state; } publicfunction getState() { return $this->_state; } publicfunction showState() { output($this->_state); } } class Memento { // 備忘錄(Memento)角色 private$_state; publicfunction __construct($state) { $this->setState($state); } publicfunction getState() { return $this->_state; } publicfunction setState($state) { $this->_state = $state;} } class Caretaker { // 負責人(Caretaker)角色 private$_memento; public functiongetMemento() { return $this->_memento; } publicfunction setMemento(Memento $memento) { $this->_memento = $memento; } } class Client { publicstatic 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) { thrownew Exception('SQL 1 update failed'); } $succ = $db->exec($sql_2); if(!$succ) { thrownew Exception('SQL 2 update failed'); } $succ = $db->exec($sql_3); if(!$succ) { throw newException('SQL 3 update failed'); } $db->commit(); } catch (Exception $exp) { $db->rollBack(); }
深度模式
1、解釋器模式(Interpreter):
定義語言的文法,并建立一個解釋器解釋該語言中的句子。每個用過字典的童鞋都懂滴。
好處:可擴展性比較好,靈活性大
弊端:可能難以維護復雜的文法
應用場景:用于成對或者一對多的需求中
2、訪問者模式(Visitor):
封裝某些用于作用于某種數據結構中各元素的操作,可以在不改變數據結構的前提下定義作用于這些元素的新操作。如銀行排號機。
好處:將相關的事物集中到一個訪問者對象中。
弊端:增加新數據結構很困難
應用場景:排隊,排號
三、總結
本篇介紹了行為型模式,行為模式涉及到算法和對象職責間的分配,行為類模式采用繼承機制在類間分派行為,TemplateMethod和Interpreter是類行為模式。行為對象模式使用對象復合而不是繼承,一些行為對象模式描述了一組相互對等的對象如何相互協作以完成其中任何一個對象都單獨無法完成的任務,如Mediator在對象間引入一個mediator對象提供了松耦合所需的間接性;Chain of Responsibility提供了更松的耦合,它通過一條候選對象鏈隱式的向一個對象發松請求,可以運行時刻決定哪些候選者參與到鏈中;Observer定義并保持了對象間的依賴關系;其它的行為對象模式常將行為封裝封裝在一個對象中,并將請求指派給它,Strategy模式將算法封裝在對象中,這樣可以方面的改變和指定一個對象所使用的算法;Command模式將請求封裝在對象中,這樣它就可以作為參數來傳遞,已可以存儲在歷史列表中或以其它方式使用;State模式封裝一個對象的狀態,使得當這個對象的狀態對象變化時,該對象可改變它的行為;Visitor模式封裝分布于多個類之間的行為;而Iterator模式則抽象了訪問和遍歷一個集合中對象的方式。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。