本文實(shí)例講述了PHP設(shè)計(jì)模式之狀態(tài)模式定義與用法。分享給大家供大家參考,具體如下:
什么是狀態(tài)設(shè)計(jì)模式
當(dāng)一個(gè)對(duì)象的內(nèi)在狀態(tài)改變時(shí)允許改變其行為,這個(gè)對(duì)象看起來(lái)像是改變了其類。
狀態(tài)模式主要解決的是當(dāng)控制一個(gè)對(duì)象狀態(tài)的條件表達(dá)式過(guò)于復(fù)雜時(shí)的情況。把狀態(tài)的判斷邏輯轉(zhuǎn)移到表示不同狀態(tài)的一系列類中,可以把復(fù)雜的判斷邏輯簡(jiǎn)化。
什么時(shí)候使用狀態(tài)模式
對(duì)象中頻繁改變非常依賴于條件語(yǔ)句。 就其自身來(lái)說(shuō), 條件語(yǔ)句本身沒(méi)有什么問(wèn)題(如switch語(yǔ)句或帶else子句的語(yǔ)句),不過(guò), 如果選項(xiàng)太多, 以到程序開(kāi)始出現(xiàn)混亂, 或者增加或改變選項(xiàng)需要花費(fèi)太多時(shí)間, 甚至成為一種負(fù)擔(dān), 這就出現(xiàn)了問(wèn)題
對(duì)于狀態(tài)設(shè)計(jì)模式, 每個(gè)狀態(tài)都有自己的具體類, 它們實(shí)現(xiàn)一個(gè)公共接口. 我們不用查看對(duì)象的控制流, 而是從另一個(gè)角度來(lái)考慮, 即對(duì)象的狀態(tài).
狀態(tài)機(jī)是一個(gè)模型, 其重點(diǎn)包括不同的狀態(tài), 一個(gè)狀態(tài)到另一個(gè)狀態(tài)的變遷, 以及導(dǎo)致?tīng)顟B(tài)改變的觸發(fā)器.
以開(kāi)燈關(guān)燈為例子, 狀態(tài)模型的本質(zhì)分為3點(diǎn):
①狀態(tài)(關(guān)燈和開(kāi)燈)
②變遷(從關(guān)燈到開(kāi)燈, 以及從開(kāi)燈到關(guān)燈)
③觸發(fā)器(燈開(kāi)關(guān))
所以狀態(tài)模式都需要一個(gè)參與者來(lái)跟蹤對(duì)象所處的狀態(tài). 以Light為例, Light需要知道當(dāng)前狀態(tài)是什么.
示例:開(kāi)燈關(guān)燈
Light.php
?php class Light { private $offState; //關(guān)閉狀態(tài) private $onState; //開(kāi)啟狀態(tài) private $currentState; //當(dāng)前狀態(tài) public function __construct() { $this->offState = new OffState($this); $this->onState = new OnState($this); //開(kāi)始狀態(tài)為關(guān)閉狀態(tài)Off $this->currentState = $this->offState; } //調(diào)用狀態(tài)方法觸發(fā)器 public function turnLightOn() { $this->currentState->turnLightOn(); } public function turnLightOff() { $this->currentState->turnLightOff(); } //設(shè)置當(dāng)前狀態(tài) public function setState(IState $state) { $this->currentState = $state; } //獲取狀態(tài) public function getOnState() { return $this->onState; } public function getOffState() { return $this->offState; } }
在構(gòu)造函數(shù)中, Light實(shí)例化IState實(shí)現(xiàn)的兩個(gè)實(shí)例-----一個(gè)對(duì)應(yīng)關(guān), 一個(gè)對(duì)應(yīng)開(kāi)
$this->offState = new OffState($this); $this->onState = new OnState($this);
這個(gè)實(shí)例化過(guò)程用到了一種遞歸, 稱為自引用(self-referral)
構(gòu)造函數(shù)參數(shù)中的實(shí)參寫(xiě)為$this, 這是Light類自身的一個(gè)引用. 狀態(tài)類希望接收一個(gè)Light類實(shí)例做參數(shù),.
setState方法是為了設(shè)置一個(gè)當(dāng)前狀態(tài) 需要一個(gè)狀態(tài)對(duì)象作為實(shí)參, 一旦觸發(fā)一個(gè)狀態(tài), 這個(gè)狀態(tài)就會(huì)向Light類發(fā)送信息, 指定當(dāng)前狀態(tài).
狀態(tài)實(shí)例
IState接口
IState.php
?php interface IState { public function turnLightOn(); public function turnLightOff(); }
該接口的實(shí)現(xiàn)類
OnState.php
?php class OnState implements IState { private $light; public function __construct(Light $light) { $this->light = $light; } public function turnLightOn() { echo "燈已經(jīng)打開(kāi)了->不做操作br />"; } public function turnLightOff() { echo "燈關(guān)閉!看不見(jiàn)帥哥chenqionghe了!br />"; $this->light->setState($this->light->getOffState()); } }
OffState.php
?php class OffState implements IState { private $light; public function __construct(Light $light) { $this->light = $light; } public function turnLightOn() { echo "燈打開(kāi)!可以看見(jiàn)帥哥chenqionghe了!br />"; $this->light->setState($this->light->getOnState()); } public function turnLightOff() { echo "燈已經(jīng)關(guān)閉了->不做操作br />"; } }
默認(rèn)狀態(tài)是OffState, 它必須實(shí)現(xiàn)IState方法turnLightOn和turnLightOff, Light調(diào)用turnLightOn方法, 會(huì)顯示(燈打開(kāi)!可以看見(jiàn)帥哥chenqionghe了), 然后將OnState設(shè)置為當(dāng)前狀態(tài), 不過(guò),如果是調(diào)用 OffState的turnLightOff方法, 就只有提示燈已經(jīng)被關(guān)閉了 不會(huì)有其他動(dòng)作.
客戶
Client的所有請(qǐng)求都是通過(guò)Light發(fā)出, Client和任何狀態(tài)類之間都沒(méi)有直接連接, 包括IState接口.下面的Client顯示了觸發(fā)兩個(gè)狀態(tài)中所有方法的請(qǐng)求.
Client.php
?php function __autoload($class_name) { include_once $class_name.'.php'; } class Client { private $light; public function __construct() { $this->light = new Light(); $this->light->turnLightOn(); $this->light->turnLightOn(); $this->light->turnLightOff(); $this->light->turnLightOff(); } } $worker = new Client();
增加狀態(tài)
對(duì)于所有的設(shè)計(jì)模式來(lái)說(shuō),很重要的一個(gè)方面是: 利用這些設(shè)計(jì)模式可以很容易地做出修改. 與其他模式一樣,狀態(tài)模式也很易于更新和改變. 下面在這個(gè)燈的示例上再加兩個(gè)狀態(tài):更亮(Brighter)和最亮(Brightest)
現(xiàn)在變成了4個(gè)狀態(tài), 序列有所改變. '關(guān)'(off)狀態(tài)只能變到"開(kāi)"(on)狀態(tài), on狀態(tài)不能變到off狀態(tài). on狀態(tài)只能變到"更亮"(brighter)狀態(tài)和"最亮"(brightest)狀態(tài). 只能最亮狀態(tài)才可能變到關(guān)狀態(tài).
改變接口
要改變的第一個(gè)參與者是接口IState, 這個(gè)接口中必須指定相應(yīng)的方法, 可以用來(lái)遷移到brighter和brightest狀態(tài).
IState.php
?php interface IState { public function turnLightOn(); public function turnLightOff(); public function turnBrighter(); public function turnBrightest(); }
現(xiàn)在所有狀態(tài)類都必須包含這4個(gè)方法, 它們都需要結(jié)合到Light類中.
改變狀態(tài)
狀態(tài)設(shè)計(jì)模式中有改變時(shí), 這些新增的改變會(huì)對(duì)模式整體的其他方面帶來(lái)影響. 不過(guò), 增加改變相當(dāng)簡(jiǎn)單, 每個(gè)狀態(tài)只有一個(gè)特定的變遷.
四個(gè)狀態(tài)
OnState.php
?php class OnState implements IState { private $light; public function __construct(Light $light) { $this->light = $light; } public function turnLightOn() { echo "不合法的操作!br />"; } public function turnLightOff() { echo "燈關(guān)閉!看不見(jiàn)帥哥chenqionghe了!br />"; $this->light->setState($this->light->getOffState()); } public function turnBrighter() { echo "燈更亮了, 看帥哥chenqionghe看得更真切了!br />"; $this->light->setState($this->light->getBrighterState()); } public function turnBrightest() { echo "不合法的操作!br />"; } }
OffState.php
?php class OffState implements IState { private $light; public function __construct(Light $light) { $this->light = $light; } public function turnLightOn() { echo "燈打開(kāi)!可以看見(jiàn)帥哥chenqionghe了!br />"; $this->light->setState($this->light->getOnState()); } public function turnLightOff() { echo "不合法的操作!br />"; } public function turnBrighter() { echo "不合法的操作!br />"; } public function turnBrightest() { echo "不合法的操作!br />"; } }
Brighter.php
?php class BrighterState implements IState { private $light; public function __construct(Light $light) { $this->light = $light; } public function turnLightOn() { echo "不合法的操作!br />"; } public function turnLightOff() { echo "不合法的操作!br />"; } public function turnBrighter() { echo "不合法的操作!br />"; } public function turnBrightest() { echo "燈最亮了, 看帥哥chenqionghe已經(jīng)帥到無(wú)敵!br />"; $this->light->setState($this->light->getBrightestState()); } }
Brightest.php
?php class BrightestState implements IState { private $light; public function __construct(Light $light) { $this->light = $light; } public function turnLightOn() { echo "燈已經(jīng)打開(kāi)了->不做操作br />"; } public function turnLightOff() { echo "燈關(guān)閉!看不見(jiàn)帥哥chenqionghe了!br />"; $this->light->setState($this->light->getOffState()); } public function turnBrighter() { echo "不合法的操作!br />"; } public function turnBrightest() { echo "不合法的操作!br />"; } }
更新Light類
Light.php
?php class Light { private $offState; //關(guān)閉狀態(tài) private $onState; //開(kāi)啟狀態(tài) private $brighterState; //更亮狀態(tài) private $brightestState;//最亮狀態(tài) private $currentState; //當(dāng)前狀態(tài) public function __construct() { $this->offState = new OffState($this); $this->onState = new OnState($this); $this->brighterState = new BrighterState($this); $this->brightestState = new BrightestState($this); //開(kāi)始狀態(tài)為關(guān)閉狀態(tài)Off $this->currentState = $this->offState; } //調(diào)用狀態(tài)方法觸發(fā)器 public function turnLightOn() { $this->currentState->turnLightOn(); } public function turnLightOff() { $this->currentState->turnLightOff(); } public function turnLightBrighter() { $this->currentState->turnBrighter(); } public function turnLigthBrightest() { $this->currentState->turnBrightest(); } //設(shè)置當(dāng)前狀態(tài) public function setState(IState $state) { $this->currentState = $state; } //獲取狀態(tài) public function getOnState() { return $this->onState; } public function getOffState() { return $this->offState; } public function getBrighterState() { return $this->brighterState; } public function getBrightestState() { return $this->brightestState; } }
更新客戶
?php function __autoload($class_name) { include_once $class_name.'.php'; } class Client { private $light; public function __construct() { $this->light = new Light(); $this->light->turnLightOn(); $this->light->turnLightBrighter(); $this->light->turnLigthBrightest(); $this->light->turnLightOff(); $this->light->turnLigthBrightest(); } } $worker = new Client();
運(yùn)行結(jié)果如下
燈打開(kāi)!可以看見(jiàn)帥哥chenqionghe了!
燈更亮了, 看帥哥chenqionghe看得更真切了!
燈最亮了, 看帥哥chenqionghe已經(jīng)帥到無(wú)敵!
燈關(guān)閉!看不見(jiàn)帥哥chenqionghe了!
不合法的操作!
九宮格移動(dòng)示例
九宮格的移動(dòng)分為4個(gè)移動(dòng):
上(Up)
下(Down)
左(Left)
右(Right)
對(duì)于這些移動(dòng),規(guī)則是要求單元格之間不能沿對(duì)角線方向移動(dòng). 另外, 從一個(gè)單元格移動(dòng)到下一個(gè)單元格時(shí), 一次只能移動(dòng)一個(gè)單元格
要使用狀態(tài)設(shè)計(jì)模式來(lái)建立一個(gè)九宮格移動(dòng)示例,
建立接口
IMatrix.php
?php interface IMatrix { public function goUp(); public function goDown(); public function goLeft(); public function goRight(); }
雖然這個(gè)狀態(tài)設(shè)計(jì)模式有9個(gè)狀態(tài), 分別對(duì)應(yīng)九個(gè)單元格, 但一個(gè)狀態(tài)最多只需要4個(gè)變遷
上下文
對(duì)于狀態(tài)中的4個(gè)變遷或移動(dòng)方法, 上下文必須提供相應(yīng)方法來(lái)調(diào)用這些變遷方法, 另外還要完成各個(gè)狀態(tài)的實(shí)例化.
Context.php
?php class Context { private $cell1; private $cell2; private $cell3; private $cell4; private $cell5; private $cell6; private $cell7; private $cell8; private $cell9; private $currentState; public function __construct() { $this->cell1 = new Cell1State($this); $this->cell2 = new Cell2State($this); $this->cell3 = new Cell3State($this); $this->cell4 = new Cell4State($this); $this->cell5 = new Cell5State($this); $this->cell6 = new Cell6State($this); $this->cell7 = new Cell7State($this); $this->cell8 = new Cell8State($this); $this->cell9 = new Cell9State($this); $this->currentState = $this->cell5; } //調(diào)用方法 public function doUp() { $this->currentState->goUp(); } public function doDown() { $this->currentState->goDown(); } public function doLeft() { $this->currentState->goLeft(); } public function doRight() { $this->currentState->goRight(); } //設(shè)置當(dāng)前狀態(tài) public function setState(IMatrix $state) { $this->currentState = $state; } //獲取狀態(tài) public function getCell1State() { return $this->cell1; } public function getCell2State() { return $this->cell2; } public function getCell3State() { return $this->cell3; } public function getCell4State() { return $this->cell4; } public function getCell5State() { return $this->cell5; } public function getCell6State() { return $this->cell6; } public function getCell7State() { return $this->cell7; } public function getCell8State() { return $this->cell8; } public function getCell9State() { return $this->cell9; } }
狀態(tài)
9個(gè)狀態(tài)表示九宮格中的不同單元格, 為了唯一顯示單元格,會(huì)分別輸出相應(yīng)到達(dá)的單元格數(shù)字, 這樣能夠更清楚地看出穿過(guò)矩陣的路線.
Cell1State
?php class Cell1State implements IMatrix { private $context; public function __construct(Context $contextNow) { $this->context = $contextNow; } public function goLeft() { echo '不合法的移動(dòng)!br />'; } public function goRight() { echo '走到strong>2/strong>br />'; $this->context->setState($this->context->getCell2State()); } public function goUp() { echo '不合法的移動(dòng)!br />'; } public function goDown() { echo '走到strong>4/strong>br />'; $this->context->setState($this->context->getCell4State()); } }
Cell2State
?php class Cell2State implements IMatrix { private $context; public function __construct(Context $contextNow) { $this->context = $contextNow; } public function goLeft() { echo '走到strong>1/strong>br />'; $this->context->setState($this->context->getCell1State()); } public function goRight() { echo '走到strong>3/strong>br />'; $this->context->setState($this->context->getCell3State()); } public function goUp() { echo '不合法的移動(dòng)!br />'; } public function goDown() { echo '走到strong>5/strong>br />'; $this->context->setState($this->context->getCell5State()); } }
Cell3State
?php class Cell3State implements IMatrix { private $context; public function __construct(Context $contextNow) { $this->context = $contextNow; } public function goLeft() { echo '走到strong>2/strong>br />'; $this->context->setState($this->context->getCell2State()); } public function goRight() { echo '不合法的移動(dòng)!br />'; } public function goUp() { echo '不合法的移動(dòng)!br />'; } public function goDown() { echo '走到strong>6/strong>br />'; $this->context->setState($this->context->getCell6State()); } }
Cell4State
?php class Cell4State implements IMatrix { private $context; public function __construct(Context $contextNow) { $this->context = $contextNow; } public function goLeft() { echo '不合法的移動(dòng)!br />'; } public function goRight() { echo '走到strong>5/strong>br />'; $this->context->setState($this->context->getCell5State()); } public function goUp() { echo '走到strong>1/strong>br />'; $this->context->setState($this->context->getCell1State()); } public function goDown() { echo '走到strong>7/strong>br />'; $this->context->setState($this->context->getCell7State()); } }
Cell5State
?php class Cell5State implements IMatrix { private $context; public function __construct(Context $contextNow) { $this->context = $contextNow; } public function goLeft() { echo '走到strong>4/strong>br />'; $this->context->setState($this->context->getCell4State()); } public function goRight() { echo '走到strong>6/strong>br />'; $this->context->setState($this->context->getCell6State()); } public function goUp() { echo '走到strong>2/strong>br />'; $this->context->setState($this->context->getCell2State()); } public function goDown() { echo '走到strong>8/strong>br />'; $this->context->setState($this->context->getCell8State()); } }
Cell6State
?php class Cell6State implements IMatrix { private $context; public function __construct(Context $contextNow) { $this->context = $contextNow; } public function goLeft() { echo '走到strong>5/strong>br />'; $this->context->setState($this->context->getCell5State()); } public function goRight() { echo '不合法的移動(dòng)!br />'; } public function goUp() { echo '走到strong>3/strong>br />'; $this->context->setState($this->context->getCell3State()); } public function goDown() { echo '走到strong>9/strong>br />'; $this->context->setState($this->context->getCell9State()); } }
Cell7State
?php class Cell7State implements IMatrix { private $context; public function __construct(Context $contextNow) { $this->context = $contextNow; } public function goLeft() { echo '不合法的移動(dòng)!br />'; } public function goRight() { echo '走到strong>8/strong>br />'; $this->context->setState($this->context->getCell8State()); } public function goUp() { echo '走到strong>4/strong>br />'; $this->context->setState($this->context->getCell4State()); } public function goDown() { echo '不合法的移動(dòng)!br />'; } }
Cell8State
?php class Cell8State implements IMatrix { private $context; public function __construct(Context $contextNow) { $this->context = $contextNow; } public function goLeft() { echo '走到strong>7/strong>br />'; $this->context->setState($this->context->getCell7State()); } public function goRight() { echo '走到strong>9/strong>br />'; $this->context->setState($this->context->getCell9State()); } public function goUp() { echo '走到strong>5/strong>br />'; $this->context->setState($this->context->getCell5State()); } public function goDown() { echo '不合法的移動(dòng)!br />'; } }
Cell9State
?php class Cell9State implements IMatrix { private $context; public function __construct(Context $contextNow) { $this->context = $contextNow; } public function goLeft() { echo '走到strong>8/strong>br />'; $this->context->setState($this->context->getCell8State()); } public function goRight() { echo '不合法的移動(dòng)!br />'; } public function goUp() { echo '走到strong>6/strong>br />'; $this->context->setState($this->context->getCell6State()); } public function goDown() { echo '不合法的移動(dòng)!br />'; } }
要想有效地使用狀態(tài)設(shè)計(jì)模式, 真正的難點(diǎn)在于要想象現(xiàn)實(shí)或模擬世界是怎么樣
客戶Client
下面從單元格5開(kāi)始進(jìn)行一個(gè)上,右,下, 下,左,上的移動(dòng)
Client.php
?php function __autoload($class_name) { include_once $class_name.'.php'; } class Client { private $context; public function __construct() { $this->context = new Context(); $this->context->doUp(); $this->context->doRight(); $this->context->doDown(); $this->context->doDown(); $this->context->doLeft(); $this->context->doUp(); } } $worker = new Client();
運(yùn)行結(jié)果如下
走到2
走到3
走到6
走到9
走到8
走到5
狀態(tài)模式與PHP
很多人把狀態(tài)設(shè)計(jì)模式看做是實(shí)現(xiàn)模擬器和游戲的主要方法.總的說(shuō)來(lái), 這確實(shí)是狀態(tài)模式的目標(biāo),不過(guò)險(xiǎn)些之外, 狀態(tài)模型(狀態(tài)引擎)和狀態(tài)設(shè)計(jì)模式在PHP中也有很多應(yīng)用.用PHP完成更大的項(xiàng)目時(shí), 包括Facebook和WordPress, 會(huì)有更多的新增特性和當(dāng)前狀態(tài)需求.對(duì)于這種不斷有改變和增長(zhǎng)的情況, 就可以采用可擴(kuò)展的狀態(tài)模式來(lái)管理.
PHP開(kāi)發(fā)人員如何創(chuàng)建包含多個(gè)狀態(tài)的程序, 將決定狀態(tài)模式的使用范圍. 所以不僅狀態(tài)機(jī)在游戲和模擬世界中有很多應(yīng)用, 實(shí)際上狀態(tài)模型還有更多適用的領(lǐng)域.只要PHP程序的用戶會(huì)用到一組有限的狀態(tài), 開(kāi)發(fā)人員就可以使用狀態(tài)設(shè)計(jì)模式.
更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門(mén)教程》、《PHP基本語(yǔ)法入門(mén)教程》、《PHP數(shù)組(Array)操作技巧大全》、《php字符串(string)用法總結(jié)》、《php+mysql數(shù)據(jù)庫(kù)操作入門(mén)教程》及《php常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總》
希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。
標(biāo)簽:工商登記 宜春 延安 澳門(mén) 佛山 常德 深圳 宿遷
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《PHP設(shè)計(jì)模式之狀態(tài)模式定義與用法詳解》,本文關(guān)鍵詞 PHP,設(shè)計(jì)模式,之,狀態(tài),模式,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。