談從魔獸看PHP設(shè)計(jì)模式(2)_PHP教程
好了,到這里初始化代碼就寫好了,現(xiàn)在還差一個(gè)控制這些初始化得類,也就是封裝他們:
<?php
class initialController {
//構(gòu)造函數(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);
$initialController->giveBuilding($player);
$initialController->giveSupply($player);
}
}
}
最后就是簡單這么一調(diào)用,就OK:
<?php
//有兩個(gè)精靈族兩個(gè)獸族
$playerArray = array(new player('NighyElf'), new player('NighyElf'), new player('ORC'), new player('ORC'));
//進(jìn)行初始化工作
$initialController = new initialController($playerArray);
這就是策略模式,他將不同情況下的算法封裝在一起。Zend framework中的Zend_Application_Resource就是用策略模式來設(shè)計(jì)的。
三、工廠模式:
問題的提出:
最初在設(shè)計(jì)模式一書中,許多設(shè)計(jì)模式都鼓勵(lì)使用松散耦合。要理解這個(gè)概念,讓我們最好談一下許多開發(fā)人員從事大型系統(tǒng)的艱苦歷程。在更改一個(gè)代碼片段時(shí),就會(huì)發(fā)生問題,系統(tǒng)其他部分 —— 您曾認(rèn)為完全不相關(guān)的部分中也有可能出現(xiàn)級(jí)聯(lián)破壞。
該問題在于緊密耦合。系統(tǒng)某個(gè)部分中的函數(shù)和類嚴(yán)重依賴于系統(tǒng)的其他部分中函數(shù)和類的行為和結(jié)構(gòu)。您需要一組模式,使這些類能夠相互通信,但不希望將它們緊密綁定在一起,以避免出現(xiàn)聯(lián)鎖。
在大型系統(tǒng)中,許多代碼依賴于少數(shù)幾個(gè)關(guān)鍵類。需要更改這些類時(shí),可能會(huì)出現(xiàn)困難。例如,假設(shè)您有一個(gè)從文件讀取的 User 類。您希望將其更改為從數(shù)據(jù)庫讀取的其他類,但是,所有的代碼都引用從文件讀取的原始類。這時(shí)候,使用工廠模式會(huì)很方便。
工廠模式是一種類,它具有為您創(chuàng)建對(duì)象的某些方法。您可以使用工廠類創(chuàng)建對(duì)象,而不直接使用 new。這樣,如果您想要更改所創(chuàng)建的對(duì)象類型,只需更改該工廠即可。使用該工廠的所有代碼會(huì)自動(dòng)更改。
問題的解決:
呵呵,估計(jì)有些phper沒看懂吧,沒關(guān)系,那是我從其他地方抄的,我們下面還是通過魔獸來進(jìn)行吧。這一部分,我看都已經(jīng)有前人寫好了,我就基本上照抄了,請(qǐng)前人不要見怪啊。呵呵。
前面選了暗夜精靈族(Nighy Elf),和獸族(ORC),因?yàn)樾【`(Wisp)能建造建筑,還能自爆。所以根據(jù)這個(gè)我們下面先寫個(gè)小精靈(Wisp)的類。
<?php
class Wisp
{
private $mHealthPoint = 120;//這是小精靈的血量
private $mArmor = 0;//這是小精靈的護(hù)甲
//小精靈能建造建筑
public function Build()
{
echo '精靈建造建筑咯。<br/>';
}
//每個(gè)小精靈被造出來時(shí)還會(huì)占用一個(gè)人口
public function __construct()
{
echo '你已經(jīng)建造了一個(gè)小精靈。<br/>';
//這里是增加已有人口的代碼
}
//每個(gè)小精靈死亡會(huì)減少你占用的人口
public function __destruct()
{
//這里是減少已有人口的代碼
}
}
把這些代碼放在Arms/ Wisp.php中。
啊,還有還有,還有苦工(Peon)的類
<?php
class Peon
{
private $mHealthPoint = 250;//這是苦工的血量
private $mArmor = 0;//這是苦工的護(hù)甲
//苦工能建造建筑
public function Build()
{
echo '苦工建造建筑咯。<br/>';
}
//每個(gè)苦工被造出來時(shí)還會(huì)占用一個(gè)人口
public function __construct()
{
echo '你已經(jīng)建造了一個(gè)苦工。<br/>';
//這里是增加已有人口的代碼
}
//每個(gè)苦工死亡會(huì)減少你占用的人口
public function __destruct()
{
//這里是減少已有人口的代碼
}
}
把這些代碼放在Arms/ Peon.php中。
等等,這樣豈不是很復(fù)雜,魔獸里面還有那么多的兵種,另外都還有兩個(gè)種族,每次創(chuàng)建一個(gè)兵就要new一個(gè),要是記不住這個(gè)兵的類名,豈不是new不了?而且如果一個(gè)兵是一個(gè)類,放在一個(gè)文件里,那是不是一開始就要把所有的幾十上百個(gè)文件都include一次啊,那效率可想而知啊。
嘿嘿,當(dāng)然是有解決辦法的啊,我們?cè)賹懸粋(gè)類把這些類都封裝起來,這個(gè)把兵種都封裝起來的類我們稱之為工廠類,他可以像生產(chǎn)產(chǎn)品一樣,來創(chuàng)建兵,幫我們對(duì)其實(shí)例化。下面我們就來看這個(gè)類怎么實(shí)現(xiàn)吧。
<?php
class CreatArms
{
public function __construct(){}
public function Creat($arms,$path = '')
{
include $path.$arms.'.php'; //包含要這個(gè)類的文件
return new $arms; //返回你創(chuàng)建的兵種對(duì)象的句柄
}
}
這樣,即使在兵種多樣的情況下,我們?nèi)匀豢梢院芊奖愕貙?shí)例化:
$creator = new CreatArms();
$w1 = $creator->Creat('兵種名','前綴或路徑');
例如創(chuàng)建小精靈:
$creator = new CreatArms();//不管創(chuàng)建啥,我都只要使用這個(gè)類
$w1 = $creator->Creat(‘Wisp’,’./Arms/’);//創(chuàng)建一個(gè)小精靈
$w1->Build();//讓小精靈造建筑
這就是傳說中的工廠模式,通過工廠模式,對(duì)于如論壇那種有很多種用戶的,特別是為了以后擴(kuò)展比較方便的,采用工廠模式,是個(gè)很好的解決方法。在zend framework中的Zend_Form、Zend_Filter、Zend_Validate就是用工廠模式來構(gòu)架的。
四、觀察者模式:
問題的提出:
觀察者模式為您提供了避免組件之間緊密耦合的另一種方法。該模式非常簡單:一個(gè)對(duì)象通過添加一個(gè)方法(該方法允許另一個(gè)對(duì)象,即觀察者 注冊(cè)自己)使本身變得可觀察。當(dāng)可觀察的對(duì)象更改時(shí),它會(huì)將消息發(fā)送到已注冊(cè)的觀察者。這些觀察者使用該信息執(zhí)行的操作與可觀察的對(duì)象無關(guān)。結(jié)果是對(duì)象可以相互對(duì)話,而不必了解原因。
問題的解決:
呵呵,上面還是抄的,看不懂沒關(guān)系,我們今天重點(diǎn)是玩魔獸。
已經(jīng)造了很長時(shí)間的兵了,現(xiàn)在可以出去帶兵打仗了,如果我去打電腦的獸族,那么電腦與那個(gè)獸族同盟的精靈族就會(huì)過來幫忙。那么如何讓他知道自己的同盟受攻擊了呢�,F(xiàn)在我們就來討論這個(gè)問題。
首先我們寫一下結(jié)盟的抽象類:
<?php
abstract class abstractAlly
{
//放置觀察者的集合,這里以簡單的數(shù)組來直觀演示
protected $oberserverCollection;
//增加觀察者的方法,參數(shù)為觀察者(也是玩家)
public function addOberserver($oberserver)
{
$this->oberserverCollection[] = new oberserver($oberserver);
}
//將被攻擊的電腦的名字通知各個(gè)觀察者
public function notify($beAttackedPlayerName)
{
//把觀察者的集合循環(huán)
foreach ($this->oberserverCollection as $oberserver)
{
//調(diào)用各個(gè)觀察者的救援函數(shù),參數(shù)為被攻擊的電腦的名字,if用來排除被攻擊的電腦的觀察者
if($oberserver->name != $beAttackedPlayerName)
$oberserver->help($beAttackedPlayerName);
}
}
abstract public function beAttacked($beAttackedPlayer);
}
下面我們就寫具體的結(jié)盟類:
<?php
class Ally extends abstractAlly
{
//構(gòu)造函數(shù),將所有電腦玩家的名稱的數(shù)組作為參數(shù)
public function __construct($allPlayer)
{
//把所有電腦玩家的數(shù)組循環(huán)
foreach ($allPlayer as $player)
{
//增加觀察者,參數(shù)為各個(gè)電腦玩家的名稱
$this->addOberserver($player);
}
}
//將被攻擊的電腦的名字通知各個(gè)觀察者
public function beAttacked($beAttackedPlayerName)
{
//調(diào)用各個(gè)觀察者的救援函數(shù),參數(shù)為被攻擊的電腦的名字,if用來排除被攻擊的電腦的觀察者
$this->notify($beAttackedPlayerName);
}
}
接著在二、策略模式中我們定義的player類中加入一個(gè)help方法
public help($beAttackedPlayerName)
{
//這里簡單的輸出,誰去救誰,最后加一個(gè)換行,便于顯示
echo $this->name." help ".$beAttackedPlayerName."<br />";
}
這樣就行了。最后就是仿真了。
<?php
//先設(shè)置敵方電腦
$allComputePlayer = array('NighyElf2', 'ORC2');
//新建電腦結(jié)盟
$Ally = new Ally($allComputePlayer);
//假設(shè)我進(jìn)攻了電腦的獸族
$Ally->beAttacked('ORC2');
這樣結(jié)盟的另一家就能接到通知,去救援。觀察者模式主要就是用在這種情況下。可以將某個(gè)狀態(tài)變化立即通知到相關(guān)的對(duì)象,相關(guān)的對(duì)象就可以采用相應(yīng)的策略。例如,zend framework中的Zend_Message就是用的觀察者模式。
分享:解析Windows XP系統(tǒng)下安裝apache+php+mysqlApache和mysql的安裝較簡單,主要是安裝前請(qǐng)保證80端口未被占用 比如 iis 以前安裝過的apache mysql 先停止運(yùn)行phpmyadmin,主要是配置文件的問題,把phpMyAdmin安裝目錄下Libraries目錄下面的Config.default.php復(fù)制到PHPmyAdmin根目錄下,改 名為Config.in
- PHPNOW安裝Memcached擴(kuò)展方法詳解
- php記錄頁面代碼執(zhí)行時(shí)間
- PHP中獎(jiǎng)概率的抽獎(jiǎng)算法程序代碼
- apache設(shè)置靜態(tài)文件緩存方法介紹
- php對(duì)圖像的各種處理函數(shù)代碼小結(jié)
- PHP 關(guān)于訪問控制的和運(yùn)算符優(yōu)先級(jí)介紹
- 關(guān)于PHP語言構(gòu)造器介紹
- php/js獲取客戶端mac地址的實(shí)現(xiàn)代碼
- php5.5新數(shù)組函數(shù)array_column使用
- PHP preg_match的匹配多國語言的技巧
- php 中序列化和json使用介紹
- php采集文章中的圖片獲取替換到本地
- 相關(guān)鏈接:
- 教程說明:
PHP教程-談從魔獸看PHP設(shè)計(jì)模式(2)
。