《PHP設(shè)計(jì)模式介紹》第三章 工廠模式(6)_PHP教程
推薦:《PHP設(shè)計(jì)模式介紹》第二章 值對象模式在所有的最簡單的程序中,大多數(shù)對象都有一個(gè)標(biāo)識(shí),一個(gè)重要的商業(yè)應(yīng)用對象,例如一個(gè)Customer或者一個(gè)SKU,有一個(gè)或者更多的屬性---id,name,email地址,這樣可以把它從同一個(gè)類的其他實(shí)例區(qū)分開
“工廠”促進(jìn)多態(tài)
控制被送回對象的內(nèi)在狀態(tài)固然重要, 但是如果促進(jìn)多態(tài)即返回相同的接口多種類的對象,可以使得工廠模式的功能更為強(qiáng)大。
讓我們再次看一下Monopoly的例子,然后執(zhí)行購買游戲中的道具的行為。在游戲中,你的任務(wù)就是買道具,包括一些基本動(dòng)作。更進(jìn)一步說, 有三種不同的道具: Street,RailRoad和Utility。所有三個(gè)類型的道具有一些共同點(diǎn): 每個(gè)道具都被一個(gè)玩家擁有; 每個(gè)都有價(jià)格;而且每個(gè)都能為它的擁有者產(chǎn)生租金只要其他的玩家在它上面登陸。但道具之間還是存在差異的,舉例來說, 計(jì)算租金的多少就取決于道具的類型。
下列的代碼展示了一個(gè)Property的基本類:
|
// PHP5 |
注:術(shù)語 – 基類
一個(gè)基類就是不能被直接實(shí)例化的類。 一個(gè)基礎(chǔ)的類包含一個(gè)或更多的基礎(chǔ)方法,這些方法必須在子類被覆蓋。一旦所有的抽象方法被覆蓋了, 子類也就產(chǎn)生了。
基類為許多相似的類創(chuàng)造了好的原型。
CalcRent() 方法必須在子類被覆蓋,從而形成一個(gè)具體的類。因此, 每個(gè)子類包括:Street,RailRoad和Utility,和必須定義的calcRent() 方法。
為實(shí)現(xiàn)以上的情況,這三個(gè)類可以定義為:
class Street extends Property {
protected $base_rent;
public $color;
public function setRent($rent) {
$this->base_rent = new Dollar($rent);
}
protected function calcRent() {
if ($this->game->hasMonopoly($this->owner, $this->color)) {
return $this->base_rent->add($this->base_rent);
}
return $this->base_rent;
}
}
class RailRoad extends Property {
protected function calcRent() {
switch($this->game->railRoadCount($this->owner)) {
case 1: return new Dollar(25);
case 2: return new Dollar(50);
case 3: return new Dollar(100);
case 4: return new Dollar(200);
default: return new Dollar;
}
}
}
class Utility extends Property {
protected function calcRent() {
switch ($this->game->utilityCount($this->owner)) {
case 1: return new Dollar(4*$this->game->lastRoll());
case 2: return new Dollar(10*$this->game->lastRoll());
default: return new Dollar;
}
}
}
每個(gè)子類都繼承了Property類,而且包括它自己的protected ClacRent() 方法。隨著所有的基礎(chǔ)方法都被定義, 每個(gè)子類都被實(shí)例化了。
為了開始游戲, 所有的Monopoly道具必須被創(chuàng)建起來。因?yàn)檫@章是介紹工廠模式的,所有Property的類型存在很多共性,你應(yīng)該想到多態(tài)性,從而建立所有需要的對象。
我們還是以道具工廠類開始。 在我住的地方,政府的Assessor(定稅人)掌握了稅務(wù)和契約, 因此我命名它為的道具定稅工廠。下一步,這個(gè)工廠將制造全部的專有道具。在真正應(yīng)用時(shí),所有的Monopoly道具的數(shù)值可能都取自于一個(gè)數(shù)據(jù)庫或者一個(gè)文本, 但是對于這一個(gè)例子來說, 可以僅僅用一個(gè)數(shù)組來代替:
class Assessor {
protected $prop_info = array(
// streets
‘Mediterranean Ave.’ => array(‘Street’, 60, ‘Purple’, 2)
,’Baltic Ave.’ => array(‘Street’, 60, ‘Purple’, 2)
//more of the streets...
,’Boardwalk’ => array(‘Street’, 400, ‘Blue’, 50)
// railroads
,’Short Line R.R.’ => array(‘RailRoad’, 200)
//the rest of the railroads...
// utilities
,’Electric Company’ => array(‘Utility’, 150)
,’Water Works’ => array(‘Utility’, 150)
);
}
Property子類需要實(shí)例化Monopoly道具�,F(xiàn)在,我們只是簡單的用一個(gè)函數(shù)定義實(shí)例化變量$game,那么再把它加入Assessor類好了。
class Assessor {
protected $game;
public function setGame($game) { $this->game = $game; }
protected $prop_info = array(/* ... */);
}
也許你會(huì)偏向于選擇使用數(shù)據(jù)庫記錄數(shù)據(jù),不會(huì)用數(shù)組, 因?yàn)橛幸淮蠖训膮?shù)不可避免地要被羅列。如果是這樣的話,可以考慮使用" 引入叁數(shù)對象 " 進(jìn)行重構(gòu)。
注:重構(gòu)-引入叁數(shù)對象
方法中如果有很多參數(shù),常常變得很復(fù)雜,而且容易導(dǎo)致錯(cuò)誤。你可以引入一個(gè)封裝參數(shù)的對象來替代一大堆的參數(shù)。舉例來說,“start date” and “end date” 叁數(shù)可以用一個(gè) DateRange 對象一起代替。
在Monopoly這個(gè)例子中,這個(gè)參數(shù)對象應(yīng)該是什么呢?PropertyInfo,怎樣?它的目的是使每個(gè)道具參數(shù)數(shù)組引入 PropertyInfo 類的構(gòu)造器中,然后返回一個(gè)新對象。目的就意味著設(shè)計(jì), 依照 TDD, 那意味著一個(gè)測試情形。
分享:《PHP設(shè)計(jì)模式介紹》第一章 編程慣用法學(xué)習(xí)一門新的語言意味著要采用新的慣用法。這章將介紹或者可能重新強(qiáng)調(diào)一些慣用法。你會(huì)發(fā)現(xiàn)這些慣用法在你要在代碼中實(shí)現(xiàn)設(shè)計(jì)模式時(shí)候是非常有用的。 在這里總結(jié)的許多編程慣用法都是很值得
- PHPNOW安裝Memcached擴(kuò)展方法詳解
- php記錄頁面代碼執(zhí)行時(shí)間
- PHP中獎(jiǎng)概率的抽獎(jiǎng)算法程序代碼
- apache設(shè)置靜態(tài)文件緩存方法介紹
- php對圖像的各種處理函數(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ì)模式介紹》第三章 工廠模式(6)
。