您好,登錄后才能下訂單哦!
<接上一篇>
5、中介者模式(Mediator):
用中介對象封裝一系列的對象交互,中介使各對象不需要顯式地相互引用。類似于郵局,郵寄者和收件者不用自己跑很遠(yuǎn)路,通過郵局就可以。
好處:簡化了對象之間的關(guān)系,減少子類的生成
弊端:中介對象可能變得非常復(fù)雜,系統(tǒng)難以維護(hù)
應(yīng)用場景:不需要顯示地建立交互
代碼實(shí)現(xiàn):
<?php /** * 優(yōu)才網(wǎng)公開課示例代碼 * * 中介者模式 Mediator * * @author 優(yōu)才網(wǎng)全棧工程師教研組 * @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、狀態(tài)模式(State) :
對象在不同狀態(tài)下表現(xiàn)出不同的行為。就像女朋友一樣,高興了牽你的手,不高興了遛狗。在兩種狀態(tài)下變現(xiàn)出不同的行為。
好處:避免if語句實(shí)用,方便增加新狀態(tài),封裝了狀態(tài)轉(zhuǎn)換規(guī)則。
弊端:增加系統(tǒng)類和對象的數(shù)量。
應(yīng)用場景:用于對象的不同功能的轉(zhuǎn)換。
代碼實(shí)現(xiàn):
<?php /** * 優(yōu)才網(wǎng)公開課示例代碼 * * 狀態(tài)模式 State * * @author 優(yōu)才網(wǎng)全棧工程師教研組 * @see http://www.ucai.cn */ function output($string) { echo $string . "\n"; } abstract class ILift { //電梯的四個(gè)狀態(tài) constOPENING_STATE = 1; //門敞狀態(tài) constCLOSING_STATE = 2; //門閉狀態(tài) constRUNNING_STATE = 3; //運(yùn)行狀態(tài) constSTOPPING_STATE = 4; //停止?fàn)顟B(tài); //設(shè)置電梯的狀態(tài) publicabstract function setState($state); //首先電梯門開啟動(dòng)作 publicabstract function open(); //電梯門有開啟,那當(dāng)然也就有關(guān)閉了 publicabstract function close(); //電梯要能上能下,跑起來 publicabstract function run(); //電梯還要能停下來 publicabstract function stop(); } /** * 電梯的實(shí)現(xiàn)類 */ class Lift extends ILift { private$state; publicfunction setState($state) { $this->state = $state; } //電梯門關(guān)閉 publicfunction close() { //電梯在什么狀態(tài)下才能關(guān)閉 switch($this->state) { case ILift::OPENING_STATE: //如果是則可以關(guān)門,同時(shí)修改電梯狀態(tài) $this->setState(ILift::CLOSING_STATE); break; case ILift::CLOSING_STATE: //如果電梯就是關(guān)門狀態(tài),則什么都不做 //do nothing; return ; break; case ILift::RUNNING_STATE: //如果是正在運(yùn)行,門本來就是關(guān)閉的,也說明都不做 //do nothing; return ; break; case ILift::STOPPING_STATE: //如果是停止?fàn)顟B(tài),本也是關(guān)閉的,什么也不做 //do nothing; return ; break; } output('Lift colse'); } //電梯門開啟 publicfunction open() { //電梯在什么狀態(tài)才能開啟 switch($this->state){ case ILift::OPENING_STATE: //如果已經(jīng)在門敞狀態(tài),則什么都不做 //do nothing; return ; break; case ILift::CLOSING_STATE: //如是電梯時(shí)關(guān)閉狀態(tài),則可以開啟 $this->setState(ILift::OPENING_STATE); break; case ILift::RUNNING_STATE: //正在運(yùn)行狀態(tài),則不能開門,什么都不做 //do nothing; return ; break; case ILift::STOPPING_STATE: //停止?fàn)顟B(tài),淡然要開門了 $this->setState(ILift::OPENING_STATE); break; } output('Lift open'); } ///電梯開始跑起來 publicfunction run() { switch($this->state){ case ILift::OPENING_STATE: //如果已經(jīng)在門敞狀態(tài),則不你能運(yùn)行,什么都不做 //do nothing; return ; break; case ILift::CLOSING_STATE: //如是電梯時(shí)關(guān)閉狀態(tài),則可以運(yùn)行 $this->setState(ILift::RUNNING_STATE); break; case ILift::RUNNING_STATE: //正在運(yùn)行狀態(tài),則什么都不做 //do nothing; return ; break; case ILift::STOPPING_STATE: //停止?fàn)顟B(tài),可以運(yùn)行 $this->setState(ILift::RUNNING_STATE); } output('Lift run'); } //電梯停止 publicfunction stop() { switch($this->state){ case ILift::OPENING_STATE: //如果已經(jīng)在門敞狀態(tài),那肯定要先停下來的,什么都不做 //do nothing; return ; break; case ILift::CLOSING_STATE: //如是電梯時(shí)關(guān)閉狀態(tài),則當(dāng)然可以停止了 $this->setState(ILift::CLOSING_STATE); break; case ILift::RUNNING_STATE: //正在運(yùn)行狀態(tài),有運(yùn)行當(dāng)然那也就有停止了 $this->setState(ILift::CLOSING_STATE); break; case ILift::STOPPING_STATE: //停止?fàn)顟B(tài),什么都不做 //do nothing; return ; break; } output('Lift stop'); } } class Client { publicstatic function test() { $lift= new Lift(); //電梯的初始條件應(yīng)該是停止?fàn)顟B(tài) $lift->setState(ILift::STOPPING_STATE); //首先是電梯門開啟,人進(jìn)去 $lift->open(); //然后電梯門關(guān)閉 $lift->close(); //再然后,電梯跑起來,向上或者向下 $lift->run(); //最后到達(dá)目的地,電梯挺下來 $lift->stop(); } } Client::test();
<?php /** * 優(yōu)才網(wǎng)公開課示例代碼 * * 狀態(tài)模式 State * * @author 優(yōu)才網(wǎng)全棧工程師教研組 * @seehttp://www.ucai.cn */ function output($string) { echo $string . "\n"; } /** * * 定義一個(gè)電梯的接口 */ abstract class LiftState{ //定義一個(gè)環(huán)境角色,也就是封裝狀態(tài)的變換引起的功能變化 protected $_context; publicfunction setContext(Context $context){ $this->_context = $context; } //首先電梯門開啟動(dòng)作 publicabstract function open(); //電梯門有開啟,那當(dāng)然也就有關(guān)閉了 publicabstract function close(); //電梯要能上能下,跑起來 publicabstract function run(); //電梯還要能停下來,停不下來那就扯淡了 publicabstract function stop(); } /** * 環(huán)境類:定義客戶感興趣的接口。維護(hù)一個(gè)ConcreteState子類的實(shí)例,這個(gè)實(shí)例定義當(dāng)前狀態(tài)。 */ class Context { //定義出所有的電梯狀態(tài) 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(); } //定一個(gè)當(dāng)前電梯狀態(tài) private $_liftState; publicfunction getLiftState() { return$this->_liftState; } publicfunction setLiftState($liftState) { $this->_liftState = $liftState; //把當(dāng)前的環(huán)境通知到各個(gè)實(shí)現(xiàn)類中 $this->_liftState->setContext($this); } publicfunction open(){ $this->_liftState->open(); } publicfunction close(){ $this->_liftState->close(); } publicfunction run(){ $this->_liftState->run(); } publicfunction stop(){ $this->_liftState->stop(); } } /** * 在電梯門開啟的狀態(tài)下能做什么事情 */ class OpenningState extends LiftState { /** * 開啟當(dāng)然可以關(guān)閉了,我就想測試一下電梯門開關(guān)功能 * */ publicfunction close() { //狀態(tài)修改 $this->_context->setLiftState(Context::$closeingState); //動(dòng)作委托為CloseState來執(zhí)行 $this->_context->getLiftState()->close(); } //打開電梯門 publicfunction open() { output('lift open...'); } //門開著電梯就想跑,這電梯,嚇?biāo)滥悖?nbsp; publicfunction run() { //donothing; } //開門還不停止? publicfunction stop() { //donothing; } } /** * 電梯門關(guān)閉以后,電梯可以做哪些事情 */ class ClosingState extends LiftState { //電梯門關(guān)閉,這是關(guān)閉狀態(tài)要實(shí)現(xiàn)的動(dòng)作 publicfunction close() { output('lift close...'); } //電梯門關(guān)了再打開,逗你玩呢,那這個(gè)允許呀 publicfunction open() { $this->_context->setLiftState(Context::$openningState); //置為門敞狀態(tài) $this->_context->getLiftState()->open(); } //電梯門關(guān)了就跑,這是再正常不過了 publicfunction run() { $this->_context->setLiftState(Context::$runningState); //設(shè)置為運(yùn)行狀態(tài); $this->_context->getLiftState()->run(); } //電梯門關(guān)著,我就不按樓層 publicfunction stop() { $this->_context->setLiftState(Context::$stoppingState); //設(shè)置為停止?fàn)顟B(tài); $this->_context->getLiftState()->stop(); } } /** * 電梯在運(yùn)行狀態(tài)下能做哪些動(dòng)作 */ class RunningState extends LiftState { //電梯門關(guān)閉?這是肯定了 publicfunction close() { //donothing } //運(yùn)行的時(shí)候開電梯門?你瘋了!電梯不會(huì)給你開的 publicfunction open() { //donothing } //這是在運(yùn)行狀態(tài)下要實(shí)現(xiàn)的方法 publicfunction run() { output('lift run...'); } //這個(gè)事絕對是合理的,光運(yùn)行不停止還有誰敢做這個(gè)電梯?!估計(jì)只有上帝了 publicfunction stop() { $this->_context->setLiftState(Context::$stoppingState); //環(huán)境設(shè)置為停止?fàn)顟B(tài); $this->_context->getLiftState()->stop(); } } /** * 在停止?fàn)顟B(tài)下能做什么事情 */ class StoppingState extends LiftState { //停止?fàn)顟B(tài)關(guān)門?電梯門本來就是關(guān)著的! publicfunction close() { //donothing; } //停止?fàn)顟B(tài),開門,那是要的! publicfunction open() { $this->_context->setLiftState(Context::$openningState); $this->_context->getLiftState()->open(); } //停止?fàn)顟B(tài)再跑起來,正常的很 publicfunction run() { $this->_context->setLiftState(Context::$runningState); $this->_context->getLiftState()->run(); } //停止?fàn)顟B(tài)是怎么發(fā)生的呢?當(dāng)然是停止方法執(zhí)行了 publicfunction stop() { output('lift stop...'); } } /** * 模擬電梯的動(dòng)作 */ class Client { publicstatic function test() { $context = new Context(); $context->setLiftState(new ClosingState()); $context->open(); $context->close(); $context->run(); $context->stop(); } } Client::test();
7、職責(zé)鏈模式 (Chainof Responsibility):
多個(gè)對象有機(jī)會(huì)處理請求,為請求發(fā)送者和接收者解耦。就像銀行里的取款機(jī),不管那一臺(tái)都可以取到錢。
好處:簡單化對象隱藏鏈結(jié)構(gòu),便于添加新職責(zé)節(jié)點(diǎn)
弊端:請求可能沒有接受者,或者被多個(gè)接收者調(diào)用,性能降低
應(yīng)用場景:處理多種請求
代碼實(shí)現(xiàn):
<?php /** * 優(yōu)才網(wǎng)公開課示例代碼 * * 職責(zé)鏈模式 Chain of Responsibility * * @author 優(yōu)才網(wǎng)全棧工程師教研組 * @seehttp://www.ucai.cn */ function output($string) { echo $string . "\n"; } /** * 加入在公司里,如果你的請假時(shí)間小于0.5天,那么只需要向leader打聲招呼就OK了。 如果0.5<=請假天數(shù)<=3天,需要先leader打聲招呼,然后部門經(jīng)理簽字。 如果3<請假天數(shù),需要先leader打聲招呼,然后到部門經(jīng)理簽字,最后總經(jīng)經(jīng)理確認(rèn)簽字, 如果請假天數(shù)超過10天,是任何人都不能批準(zhǔn)的。 */ /** * 抽象處理者角色(Handler:Approver):定義一個(gè)處理請求的接口,和一個(gè)后繼連接(可選) * */ 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):處理它所負(fù)責(zé)的請求,可以訪問后繼者,如果可以處理請求則處理,否則將該請求轉(zhuǎn)給他的后繼者。 * */ 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)); // 已經(jīng)跟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)); // 部門經(jīng)理簽字 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)); // 總經(jīng)理簽字 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'); //請求實(shí)例 $request = new Request('ucai',4,'休息'); $leader->setSuccessor($manager); $manager->setSuccessor($generalManager); $result = $leader->handleRequest($request); } } Client::test();
8、策略模式(Strategy):
定義一系列算法,把每一個(gè)算法封裝起來,并且使它們可相互替換。就像籃球隊(duì)里的球員,場上的和場下休息的。教練可以讓場上的下來,也可以讓場下的上陣。
好處:定義可重用的一系列算法和行為,并且消除了if else語句
弊端:調(diào)用端必須知道所有策略類
應(yīng)用場景:用于對象間的替換
代碼實(shí)現(xiàn):
<?php /** * 優(yōu)才網(wǎng)公開課示例代碼 * * 策略模式 Strategy * * @author 優(yōu)才網(wǎng)全棧工程師教研組 * @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):
保存對象在一時(shí)刻的狀態(tài)。親,還記得“老師來了記得叫我一下”的同桌的他嗎?
好處:給用戶提供了一種可以恢復(fù)狀態(tài)的機(jī)制
弊端:消耗資源
應(yīng)用場景:用于需要保存的數(shù)據(jù)
代碼實(shí)現(xiàn):
<?php /** * 優(yōu)才網(wǎng)公開課示例代碼 * * 備忘錄模式 Memento * * @author 優(yōu)才網(wǎng)全棧工程師教研組 * @seehttp://www.ucai.cn */ function output($string) { echo $string . "\n"; } class Originator { // 發(fā)起人(Originator)角色 private$_state; publicfunction __construct() { $this->_state = ''; } publicfunction createMemento() { // 創(chuàng)建備忘錄 returnnew Memento($this->_state); } publicfunction restoreMemento(Memento $memento) { // 將發(fā)起人恢復(fù)到備忘錄對象記錄的狀態(tài)上 $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 { // 負(fù)責(zé)人(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(); /* 創(chuàng)建備忘 */ $memento = $org->createMemento(); /* 通過Caretaker保存此備忘 */ $caretaker = new Caretaker(); $caretaker->setMemento($memento); /* 改變目標(biāo)對象的狀態(tài) */ $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):
定義語言的文法,并建立一個(gè)解釋器解釋該語言中的句子。每個(gè)用過字典的童鞋都懂滴。
好處:可擴(kuò)展性比較好,靈活性大
弊端:可能難以維護(hù)復(fù)雜的文法
應(yīng)用場景:用于成對或者一對多的需求中
2、訪問者模式(Visitor):
封裝某些用于作用于某種數(shù)據(jù)結(jié)構(gòu)中各元素的操作,可以在不改變數(shù)據(jù)結(jié)構(gòu)的前提下定義作用于這些元素的新操作。如銀行排號機(jī)。
好處:將相關(guān)的事物集中到一個(gè)訪問者對象中。
弊端:增加新數(shù)據(jù)結(jié)構(gòu)很困難
應(yīng)用場景:排隊(duì),排號
三、總結(jié)
本篇介紹了行為型模式,行為模式涉及到算法和對象職責(zé)間的分配,行為類模式采用繼承機(jī)制在類間分派行為,TemplateMethod和Interpreter是類行為模式。行為對象模式使用對象復(fù)合而不是繼承,一些行為對象模式描述了一組相互對等的對象如何相互協(xié)作以完成其中任何一個(gè)對象都單獨(dú)無法完成的任務(wù),如Mediator在對象間引入一個(gè)mediator對象提供了松耦合所需的間接性;Chain of Responsibility提供了更松的耦合,它通過一條候選對象鏈隱式的向一個(gè)對象發(fā)松請求,可以運(yùn)行時(shí)刻決定哪些候選者參與到鏈中;Observer定義并保持了對象間的依賴關(guān)系;其它的行為對象模式常將行為封裝封裝在一個(gè)對象中,并將請求指派給它,Strategy模式將算法封裝在對象中,這樣可以方面的改變和指定一個(gè)對象所使用的算法;Command模式將請求封裝在對象中,這樣它就可以作為參數(shù)來傳遞,已可以存儲(chǔ)在歷史列表中或以其它方式使用;State模式封裝一個(gè)對象的狀態(tài),使得當(dāng)這個(gè)對象的狀態(tài)對象變化時(shí),該對象可改變它的行為;Visitor模式封裝分布于多個(gè)類之間的行為;而Iterator模式則抽象了訪問和遍歷一個(gè)集合中對象的方式。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。