




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、使市場前段時間看到有人用魔獸來解釋設計模式,感覺很有意思,于是我把它改了改,又添加了些設計模式內(nèi)容,今天發(fā)出來。有些地方借鑒了前人的內(nèi)容,沒有注明,請前人不要見怪啊。這里用大家感興趣的魔獸3來討論PHP的幾種常見的設計模式:單件模式、策略模式、工廠模式、觀察者模式。今天就講這四個吧,以后繼續(xù)。這些設計模式,都是針對面向?qū)ο髞碚f的,所以都用PHP5,另外在這里我想說的是PHP4從2008年8月8日(我記得是和北京奧運會同一天,沒查證,呵呵)的時候官方就發(fā)了最后一個PHP4的補丁,這意味這PHP4的時代已經(jīng)終結,所以,我建議大家現(xiàn)在就別理PHP4吧,就以PHP5來說吧。一、單件模式:問題的提出:某
2、些應用程序資源是獨占的,因為有且只有一個此類型的資源。例如,通過數(shù)據(jù)庫句柄到數(shù)據(jù)庫的連接是獨占的。您希望在應用程序中共享數(shù)據(jù)庫句柄,因為在保持連接打開或關閉時,它是一種開銷,在獲取單個頁面的過程中更是如此。問題的解決:那么下面我們就開始玩魔獸吧。首先雙擊war3.exe,這時候就開始運行魔獸了。我們用代碼來實現(xiàn)吧。<?phpclass War3 public function _construct()echo "War3 is Running.","<br />"$war = new War3();運行!很好,輸出War3 is Run
3、ning.我們已經(jīng)可以開始游戲了,但是,如果我在代碼末尾再加入$war2 = new War3();$war3 = new War3();會怎么樣呢?我們試試,輸出結果:War3 is Running.War3 is Running.War3 is Running.完了,如果不小心雙擊了兩次就開了3個魔獸,那如果再雙擊幾次,那電腦肯定爆掉。我們還是來想想解決方法吧。既然我們不能這么隨意的就把這個類實例化了,那么我們就把構造函數(shù)改成私有方法。class War3 private function _construct()echo "War3 is Running.",&quo
4、t;<br />"可是私有變量外部是無法訪問的,這樣以來,我們就連一個都打不開了啊。別急,我們再給他加一個不用通過實例化,外部也能訪問的函數(shù),那就是靜態(tài)函數(shù),class War3 private function _construct()echo "War3 is Running.","<br />" public static function runWar() 通過這個靜態(tài)的方法runWar()我們來控制類War3的實例化,那么還缺上一個標識,我們再創(chuàng)建一個標識,通過這個標識來表示我們的類是否已經(jīng)實例化,如果實例化,
5、直接返回句柄就行了。把類修改成class War3 protected static $_instance = null;private function _construct()echo "War3 is Running.","<br />" public static function runWar()if (null = self:$_instance) self:$_instance = new self();return self:$_instance;當然,我們運行魔獸時的實例化也要換種方法,就通過$war = War3:runW
6、ar();就能開始玩魔獸了,好了,下面把完整的代碼附上來:<?phpclass War3 protected static $_instance = null;private function _construct()echo "War3 is Running.","<br />"public static function runWar()if (null = self:$_instance) self:$_instance = new self();return self:$_instance;$war = War3:runWar(
7、);$war2 = War3:runWar();$war3 = War3:runWar();運行一下,結果是:War3 is Running.太好了,我雙擊了這么多次,也就只運行了一個魔獸,現(xiàn)在隨便你怎么打開,機子都不會爆掉了。這就是傳說中的單價模式,主要用于一些很占資源的而且實例僅有一個實例就夠用的東西,比如,zend framework中的Zend_Controller_Front前端控制器,就是采用單價模式來設計的,大家有興趣的話可以看看那個。二、策略模式:問題的提出:在此模式中,算法是從復雜類提取的,因而可以方便地替換。例如,如果要更改搜索引擎中排列頁的方法,則策略模式是一個不錯的選擇
8、。思考一下搜索引擎的幾個部分 一部分遍歷頁面,一部分對每頁排列,另一部分基于排列的結果排序。在復雜的示例中,這些部分都在同一個類中。通過使用策略模式,您可將排列部分放入另一個類中,以便更改頁排列的方式,而不影響搜索引擎的其余代碼。問題的解決:呵呵,不講那么復雜,剛才魔獸好不容易打開了,我們還是玩魔獸好了。下面我們選battle,哇好多種族啊,有人族(Human),獸族(ORC),暗夜精靈族(Nighy Elf),不死族(Undead)。我選精靈族(Nighy Elf),再選一個精靈族和兩個獸族(ORC),一個獸族和我是一家的,另一個精靈族和獸族是另一家的。每一個玩家在進入游戲后都會得到一些資源
9、,如一個大廳,五個小精靈(苦工)和一個礦山。這些可以稱為是初始化的一些東西,這里我們就可以用到策略模式來封裝這些初始化。進入正題,首先我們來構建一個玩家類:<?phpclass player/玩家名字protected $_name;/種族protected $_race;/隊伍protected $army;/建筑protected $building;/人口protected $population;/黃金protected $gold;/木材protected $wood;/構造函數(shù),設定所屬種族public function _construct($race)$this->
10、race = $race;/_get()方法用來獲取保護屬性private function _get($property_name)if(isset($this->$property_name) return($this->$property_name);else return(NULL);/_set()方法用來設置保護屬性private function_set($property_name,$value)$this->$property_name=$value;接著,我們再建一個玩家初始化的接口,<?phpinterface initialPlayer/制造初始化
11、的部隊public function giveArmy($player);/制造初始化的建筑public function giveBuilding($player);/初始化資源public function giveSource($player);好了,到這里我們就該對這個接口來實現(xiàn)了,為了方便,我只選了兩個種族,就只寫這兩個種族的初始化了:首先是精靈族:<?phpclass NighyElfInitial implements initialPlayer/制造初始化的部隊public function giveArmy($player)/五個小精靈for($i=0; $i<=
12、5;$i+)$creator = new CreatArms();/這個是創(chuàng)建部隊類,在后面得工廠模式中會用到,這里我就不多說了$player->army = $creator->Creat('Wisp','./Arms/');/制造初始化的建筑public function giveBuilding($player)$creator = new CreatBuildings();/一個基地$player->building = $creator->Creat('TownHall','./Buildings/
13、9;);/一個礦場$player->building = $creator->Creat('Mine','./Buildings/');/初始化人口上限public function giveSource($player)$player->population= 10;$player->gold= 1000;$player->wood= 100;接下來是獸族:<?phpclass ORCInitial implements initialPlayer/制造初始化的部隊public function giveArmy($play
14、er)/五個苦工for($i=0; $i<=5;$i+)$creator = new CreatArms();/這個是創(chuàng)建部隊類,在后面得工廠模式中會用到,這里我就不多說了$player->army = $creator->Creat('Peon','./Arms/');/制造初始化的建筑public function giveBuilding($player)$creator = new CreatBuildings();/一個基地$player->building = $creator->Creat('TownHall&
15、#39;,'./Buildings/');/一個礦場$player->building = $creator->Creat('Mine','./Buildings/');/初始化人口上限public fu nction giveSource($player)$player->population= 10;$player->gold= 1000;$player->wood= 100;好了,到這里初始化代碼就寫好了,現(xiàn)在還差一個控制這些初始化得類,也就是封裝他們:<?phpclass initialControll
16、er /構造函數(shù),參數(shù)為玩家的數(shù)組public function _construct($playerArray)foreach ($playerArray as $player)switch ($player->race)case 'NighyElf':$initialController = new NighyElfInitial();break;case 'ORC':$initialController = new ORCInitial();break;$initialController->giveArmy($player);$initial
17、Controller->giveBuilding($player);$initialController->giveSupply($player);最后就是簡單這么一調(diào)用,就OK:<?php/有兩個精靈族兩個獸族$playerArray = array(new player('NighyElf'), new player('NighyElf'), new player('ORC'), new player('ORC');/進行初始化工作$initialController = new initialControl
18、ler($playerArray);這就是策略模式,他將不同情況下的算法封裝在一起。Zend framework中的Zend_Application_Resource就是用策略模式來設計的。三、工廠模式:問題的提出:最初在設計模式一書中,許多設計模式都鼓勵使用松散耦合。要理解這個概念,讓我們最好談一下許多開發(fā)人員從事大型系統(tǒng)的艱苦歷程。在更改一個代碼片段時,就會發(fā)生問題,系統(tǒng)其他部分 您曾認為完全不相關的部分中也有可能出現(xiàn)級聯(lián)破壞。該問題在于緊密耦合。系統(tǒng)某個部分中的函數(shù)和類嚴重依賴于系統(tǒng)的其他部分中函數(shù)和類的行為和結構。您需要一組模式,使這些類能夠相互通信,但不希望將它們緊密綁定在一起,以避
19、免出現(xiàn)聯(lián)鎖。在大型系統(tǒng)中,許多代碼依賴于少數(shù)幾個關鍵類。需要更改這些類時,可能會出現(xiàn)困難。例如,假設您有一個從文件讀取的 User 類。您希望將其更改為從數(shù)據(jù)庫讀取的其他類,但是,所有的代碼都引用從文件讀取的原始類。這時候,使用工廠模式會很方便。工廠模式是一種類,它具有為您創(chuàng)建對象的某些方法。您可以使用工廠類創(chuàng)建對象,而不直接使用 new。這樣,如果您想要更改所創(chuàng)建的對象類型,只需更改該工廠即可。使用該工廠的所有代碼會自動更改。問題的解決:呵呵,估計有些phper沒看懂吧,沒關系,那是我從其他地方抄的,我們下面還是通過魔獸來進行吧。這一部分,我看都已經(jīng)有前人寫好了,我就基本上照抄了,請前人不要
20、見怪啊。呵呵。前面選了暗夜精靈族(Nighy Elf),和獸族(ORC),因為小精靈(Wisp)能建造建筑,還能自爆。所以根據(jù)這個我們下面先寫個小精靈(Wisp)的類。<?phpclass Wispprivate $mHealthPoint = 120;/這是小精靈的血量private $mArmor = 0;/這是小精靈的護甲/小精靈能建造建筑public function Build()echo '精靈建造建筑咯。<br/>'/每個小精靈被造出來時還會占用一個人口public function _construct()echo '你已經(jīng)建造了一個小
21、精靈。<br/>'/這里是增加已有人口的代碼/每個小精靈死亡會減少你占用的人口public function _destruct()/這里是減少已有人口的代碼把這些代碼放在Arms/ Wisp.php中。啊,還有還有,還有苦工(Peon)的類<?phpclass Peonprivate $mHealthPoint = 250;/這是苦工的血量private $mArmor = 0;/這是苦工的護甲 /苦工能建造建筑public function Build()echo '苦工建造建筑咯。<br/>' /每個苦工被造出來時還會占用一個人口pu
22、blic function _construct()echo '你已經(jīng)建造了一個苦工。<br/>'/這里是增加已有人口的代碼/每個苦工死亡會減少你占用的人口public function _destruct()/這里是減少已有人口的代碼把這些代碼放在Arms/ Peon.php中。等等,這樣豈不是很復雜,魔獸里面還有那么多的兵種,另外都還有兩個種族,每次創(chuàng)建一個兵就要new一個,要是記不住這個兵的類名,豈不是new不了?而且如果一個兵是一個類,放在一個文件里,那是不是一開始就要把所有的幾十上百個文件都include一次啊,那效率可想而知啊。嘿嘿,當然是有解決辦法的啊
23、,我們再寫一個類把這些類都封裝起來,這個把兵種都封裝起來的類我們稱之為工廠類,他可以像生產(chǎn)產(chǎn)品一樣,來創(chuàng)建兵,幫我們對其實例化。下面我們就來看這個類怎么實現(xiàn)吧。<?phpclass CreatArmspublic function _construct()public function Creat($arms,$path = '')include $path.$arms.'.php' /包含要這個類的文件return new $arms; /返回你創(chuàng)建的兵種對象的句柄這樣,即使在兵種多樣的情況下,我們?nèi)匀豢梢院芊奖愕貙嵗?creator = new C
24、reatArms();$w1 = $creator->Creat('兵種名','前綴或路徑');例如創(chuàng)建小精靈:$creator = new CreatArms();/不管創(chuàng)建啥,我都只要使用這個類$w1 = $creator->Creat(Wisp,./Arms/);/創(chuàng)建一個小精靈$w1->Build();/讓小精靈造建筑這就是傳說中的工廠模式,通過工廠模式,對于如論壇那種有很多種用戶的,特別是為了以后擴展比較方便的,采用工廠模式,是個很好的解決方法。在zend framework中的Zend_Form、Zend_Filter、Zend_V
25、alidate就是用工廠模式來構架的。四、觀察者模式:問題的提出:觀察者模式為您提供了避免組件之間緊密耦合的另一種方法。該模式非常簡單:一個對象通過添加一個方法(該方法允許另一個對象,即觀察者 注冊自己)使本身變得可觀察。當可觀察的對象更改時,它會將消息發(fā)送到已注冊的觀察者。這些觀察者使用該信息執(zhí)行的操作與可觀察的對象無關。結果是對象可以相互對話,而不必了解原因。問題的解決:呵呵,上面還是抄的,看不懂沒關系,我們今天重點是玩魔獸。已經(jīng)造了很長時間的兵了,現(xiàn)在可以出去帶兵打仗了,如果我去打電腦的獸族,那么電腦與那個獸族同盟的精靈族就會過來幫忙。那么如何讓他知道自己的同盟受攻擊了呢?,F(xiàn)在我們就來討
26、論這個問題。首先我們寫一下結盟的抽象類:<?phpabstract class abstractAlly/放置觀察者的集合,這里以簡單的數(shù)組來直觀演示protected $oberserverCollection;/增加觀察者的方法,參數(shù)為觀察者(也是玩家)public function addOberserver($oberserver)$this->oberserverCollection = new oberserver($oberserver);/將被攻擊的電腦的名字通知各個觀察者public function notify($beAttackedPlayerName)/把觀察者的集合循環(huán)foreach ($this->oberserverCollection as $oberserver)/調(diào)用各個觀察者的救援函數(shù),參數(shù)為被攻擊的電腦的名字,if用來排除被攻擊的電腦的觀察者if($oberserver->name != $beAttackedPlayerName)$oberserver->help($beAttackedPlayerName); abstract public function
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
評論
0/150
提交評論