1、組合模式
這個(gè)我覺(jué)得書(shū)上的例子很不錯(cuò)
游戲中的戰(zhàn)斗單元,單元可以組合成強(qiáng)大的部隊(duì),一起移動(dòng)、戰(zhàn)斗和防守(表示組合后的東西,跟原來(lái)的單個(gè)東西,有相同的接口,即相同的使用方式。你只要直接調(diào)用move(),不管他是單個(gè)步兵,還是一個(gè)連),總結(jié)起來(lái)就是,單兵和部隊(duì)都繼承自戰(zhàn)斗單元,部隊(duì)又組合了很多單兵。
開(kāi)始,一個(gè)簡(jiǎn)單的
<?php
abstract class Unit
{
// 返回該作戰(zhàn)單元的戰(zhàn)斗力
abstract public function bombardStrength();
}
class Archer extends Unit
{
public function bombardStrength()
{
return 4;
}
}
class LaserCannonUnit extends Unit
{
public function bombardStrength()
{
return 44;
}
}
// 上面兩個(gè)為單兵,下面開(kāi)始把他們組合成一支軍隊(duì)
class Army
{
private $units = [];
public function addUnit(Unit $unit)
{
array_push($this->units, $unit);
}
public function bombardStrength()
{
$ret = 0;
foreach ($this->units as $unit) {
$ret += $unit->bombardStrength();
}
return $ret;
}
}
$army = new Army();
$army->addUnit(new Archer());
$army->addUnit(new LaserCannonUnit());
echo $army->bombardStrength();
更詳細(xì)的看書(shū)吧,關(guān)于如何一步步優(yōu)化這個(gè)例子!最終的結(jié)果是,Army和TroopCarrier繼承自CompositeUnit,而CompositeUnit繼承自Unit,CompositeUnit類(lèi),有自己擴(kuò)展的addUnit和removeUnit方法。
2、裝飾模式
書(shū)上的例子是,一個(gè)地表類(lèi)Plains,繼承自區(qū)域類(lèi)Tile,然后有鉆石地表類(lèi)DiamondPlains和污染地表類(lèi)PollutedPlains繼承自Plains類(lèi)。
現(xiàn)在我們需要一個(gè)既有鉆石,又受到污染的地表,類(lèi),當(dāng)然,首先立馬想到的就是組合,出個(gè)組合類(lèi)
PollutedDiamondPlains。
然而,書(shū)上的例子,看上去似乎可以這樣。但是如果加上更多的地表類(lèi)型,比如濕地地表類(lèi)、草皮地表、干涸地表等,有些是可以隨意組合的,這樣類(lèi)就會(huì)爆炸式增長(zhǎng)。
現(xiàn)在就需要裝飾模式了。
<?php
abstract class Tile
{
abstract public function getWealthFactor();
}
class Plains extends Tile
{
private $wealth_factor = 2;
public function getWealthFactor()
{
return $this->wealth_factor;
}
}
abstract class TileDecorator extends Tile
{
protected $tile;
public function __construct(Tile $tile)
{
$this->tile = $tile;
}
}
class DiamondDecorator extends TileDecorator
{
function getWealthFactor()
{
return $this->tile->getWealthFactor() + 2;
}
}
class PollutionDecorator extends TileDecorator
{
function getWealthFactor()
{
return $this->tile->getWealthFactor() - 4;
}
}
$tile = new Plains();
echo $tile->getWealthFactor(), PHP_EOL; // 2
// 相當(dāng)于,任你自由組合,這里是把鉆石和地表組合
$tile = new DiamondDecorator(new Plains());
echo $tile->getWealthFactor(), PHP_EOL; // 4
// 這里是把污染和鉆石和地表組合
$tile = new PollutionDecorator(new DiamondDecorator(new Plains()));
echo $tile->getWealthFactor(), PHP_EOL; // 0
比如,我現(xiàn)在加入一個(gè)WetDecorator類(lèi),就可以組合出鉆石濕地、污染濕地、鉆石污染濕地來(lái)了,靠組合模式的話,得添加3個(gè)類(lèi)。。
3、外觀模式(Facade,或者叫門(mén)面模式)
自我理解:外觀模式隱藏一系列相互關(guān)聯(lián)的操作到類(lèi)中,并放出適當(dāng)?shù)慕涌冢ǚ椒ǎ┮怨┱{(diào)用并返回相應(yīng)的數(shù)據(jù)。而不是建一堆變量,在一堆函數(shù)種傳來(lái)傳去。
書(shū)中的例子:
<?php
// 目的:解析這樣的數(shù)據(jù)"234-ladies_jumper 55"
// 普通過(guò)程式
function get_product_file_lines($file)
{
return file($file);
}
function get_product_object_from_id($id, $product_name)
{
return new Product($id, $product_name);
}
function get_name_from_line($line)
{
if (preg_match("/.*-(.*)\s\d+/", $line, $array)) {
return str_replace('_', ' ', $array[1]);
}
return '';
}
function get_id_from_line($line)
{
if (preg_match("/^(\d{1,3})-/", $line, $array)) {
return $array[1];
}
return -1;
}
class Product
{
public $id;
public $name;
function __construct($id, $name)
{
$this->id = $id;
$this->name = $name;
}
}
// 測(cè)試
$lines = get_product_file_lines('test.txt');
$objects = [];
foreach ($lines as $line) {
$id = get_id_from_line($line);
$name = get_name_from_line($line);
$objects[$id] = get_product_object_from_id($id, $name);
}
如果你做出來(lái)的東西,給別人用,別人還要這樣使用的話,估計(jì)會(huì)打死你吧。
接下來(lái)用類(lèi)包裝一下
class ProductFacade
{
private $products = [];
function __construct($file)
{
$this->file = $file;
$this->compile();
}
private function compile()
{
$lines = get_product_file_lines($this->file);
foreach ($lines as $line) {
$id = get_id_from_line($line);
$name = get_name_from_line($line);
$this->products[$id] = get_product_object_from_id($id, $name);
}
}
public function getProducts()
{
return $this->products;
}
public function getProduct($id)
{
return $this->products[$id];
}
}
$facade = new ProductFacade('test.txt');
echo $facade->getProduct(234)->name;