簡(jiǎn)單記錄設(shè)計(jì)模式02(組合、裝飾、外觀)

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é)果是,ArmyTroopCarrier繼承自CompositeUnit,而CompositeUnit繼承自UnitCompositeUnit類(lèi),有自己擴(kuò)展的addUnitremoveUnit方法。

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;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容