策略模式 :定義了算法族,分別封裝起來,讓算法之間可以替換,此模式的讓算法的變化獨立於使用算法的客戶。
模式精髓 :把應用中可能會變的的代碼取出來,並獨立封裝起來,便於以後更容易的改動或者擴充此部分,而不會影響到其它部分。
實例分析:卡牌遊戲中,戰鬥結算過程。
在在我們的項目中,對於不同的戰鬥類型有不同的結算方式,例如:
1)玩家之間的戰鬥過程中,玩家的裝備有機率的摔壞,如果戰鬥勝利,可以搶奪對方的道具,銀幣。
2)玩家與世界BOSS戰鬥,勝利可以俘虜BOSS
3)玩家與海盜戰鬥的結算,可以搶奪海盜的銀幣
4)玩家與普通NPC戰鬥,會觸發一個“冷卻時間"機關,表示,一段時間內,玩家不會再遇到這個NPC。
5)可能後續還會開發各種戰鬥,會面臨着各種不同的計算方法。
思考方向:考慮到戰鬥結算是戰鬥流程中最容易變化的部分,我們需要把它獨立封裝起來,便於以後擴充或者修改,如何封裝成爲了我們思考的重點,這裏我們採用策略模式,把各種方法封裝成類。
類關係圖如下:
父類的結算函數如下:
/**
* 獲取戰鬥結算器實例
*
* @return Model_Battle_Finisher_Abstract
*/
public function getFinisher()
{
if (! $this->_finisher) {
$class = 'Model_Battle_Finisher_' . $this->_vsType;
$this->_finisher = new $class($this);
}
return $this->_finisher;
}
疑問:用一個類表示一個行爲,是不是有點怪怪的,類不是應該表示某種“東西”嗎,類不是應該同時具有狀態和行爲嗎?
回答:在面向對象的系統中,確實類都會有狀態和行爲屬性和方法),只是在本例中,類恰好是一個行爲,其實這個行爲也可以有屬性,比如是否結算。
設計原則: 多用組合,少用繼承。組合比繼承具有更好的擴展性。
面向接口編程,不要面向實現編程,在我們的項目中,我感觸最深的是面向接口編程(抽象類),比如 我要做一個裝備系統,我就要考慮到不同類型的裝備,統一接口,而不是分別實現這些裝備類。