設計模式學習筆記 - 2

寫在前面

今日特餐:策略模式

接續上一篇筆記《設計模式學習筆記 - 1》,瞭解了基本的物件導向原則,
今天要正式進入設計模式的內容,未來每一篇的前言,都會先破題內容會涵蓋哪一個或哪一些設計模式,方便日後查找或要補充的時候,可以更快速的找到對應的內容。

以下正文:

STRATEGY 策略模式

可以定義和封裝一系列的演算法,並且讓它們是可替換/對調的。這個模式可以讓你在不影響用戶端的情況下獨立改變演算法。

換句話說,將可能會需要被替換的實作內容抽離出來,多經過一個interface介面來將實做面隔離開來,簡單的例子像是資料庫連線,可能會遇到開發使用mysql,但是實際要部屬的時候,客戶指定要用postgreSQL。
在不討論語法有不同的問題的前提下,若我們是在每個使用資料庫的地方,都有留下連線資料庫的語法,這個時候就需要把整個專案中的連線方式都一一改過。
但如果我們連線資料庫是透過同一個介面,那只要替換掉實做的方式,就可以很快的完成變更。

書上的設計謎題:

有一款冒險遊戲,要離開新手村展開冒險旅程之前,需要先選擇職業(角色),每個職業會使用的武器不同,武器的使用方式也不同,職業與武器的攻擊模式可以參考下圖:
strage

每個職業在冒險的旅程中,可能會學到不同武器的使用方式,所以在每次戰鬥的時候,都應該保留可以選擇要使用的武器,呼叫useWeapon()方法,使怪物受傷。

  • 角色抽象類別

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?php //>
    Abstract class Character
    {
    public function setWeapon(WeaponBehavior $weaponBehavior) {
    $this->weaponBehavior = $weaponBehavior;
    }

    protected function fight() {
    //DO SOMETHING
    }

    }
  • King

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <?php //>
    class King extends Character
    {
    /** @var WeaponBehavior */
    private $weaponBehavior;

    public function __construct() {
    echo "I am the King!";
    echo PHP_EOL;
    }

    public function setWeapon(WeaponBehavior $weaponBehavior) {
    $this->weaponBehavior = $weaponBehavior;
    }

    public function fight() {
    $useWeapon = $this->weaponBehavior->useWeapon();
    echo $useWeapon['action'];
    echo PHP_EOL;
    echo 'Cause Damage: ' . $useWeapon['damage'];
    }

    }
  • WeaponBehavior Interface

    1
    2
    3
    4
    5
    <?php //>
    Interface WeaponBehavior
    {
    public function useWeapon();
    }
  • SwordBehavior infrastructure

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php //>
    class SwordBehavior implements WeaponBehavior
    {
    public function useWeapon() {
    $action = 'Swing A Sword';
    $damage = 50;

    return ['action' => $action, 'damage' => $damage];
    }
    }
  • 測試

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php //>
    $character = new King();
    $weapon = new SwordBehavior();
    $character->setWeapon($weapon);
    $character->fight();

    # 輸出結果
    # I am the King!
    # Swing A Sword
    # Cause Damage: 50

以上簡單用角色-國王,武器-劍來作為範例,未來冒險家要出新手村的時候,就可以有一個選擇角色的機制,去實例化各個角色;
遇到怪物的時候,就可以根據角色會使用的武器,來作為攻擊的方法。
如果要擴大一點,可能還可以延伸變成每個角色使用武器所造成的傷害會不同,還可以熟練使用武器的方式等等,就可以在現有基礎下進行擴展及延伸。

今天的筆記-策略模式到這邊告一段落,如果有謬誤的地方,歡迎email 給我指正或來信討論,謝謝!