[設計模式] Strategy Pattern(策略模式) Part 2

Strategy Pattern(策略模式) Part 1裡面我們提到,如果我們裡用繼承父類別的方法,就會造成子類別被強迫實作他不需要的方法,有沒有更好的方式呢?

我們觀察到,每個角色共同擁有的功能是【攻擊】,只是攻擊的武器不同,因此,我們可以把攻擊這個方法獨立抽出來。先建立一個叫做Attack的Interface:


public interface Attack
{
    void useWeapon();
}


接著我們針對三個武器建立三個Class,分別是KnifeBehavior、SwordBehavior和AxeBehavior,同時這三個類別要去實作Attack這個介面:


public class KnifeBehavior implements Attack
{
     public void useWeapon()
     {
          System.out.println("Attack by Knife");
     }
}



public class SwordBehavior implements Attack
{
     public void useWeapon()
     {
          System.out.println("Attack by Sword");
     }
}



public class AxeBehavior implements Attack
{
     public void useWeapon()
     {
          System.out.println("Attack by Axe");
     }
}


接著,我們可以在原來角色的類別(Character)中,增加一個 setFightAction(Attack attack);的方法,這個方法可以讓實作他的角色類別依照需要來動態的產生不同的攻擊方法,因此,我們原本的角色類別變成:

public abstract class Character {
    public abstract void fight();
    public abstract void action();
    public abstract void char();
    public abstract void setFightAction(Attack attack);
}

如此一來,實作角色類別的個別角色(King、Queen和Knight)的程式就會變成:

public class King extends Character {

     Attack attack;

     @Override
     public void action() {}

     @Override
     public void chat() {}

     @Override
     public void fight() {
          f.useWeapon();
     }

     @Override
     public void setFightAction(Attack attack) {
          this.attack = attack;
     }
}


最後,我們要使用每個角色時,只需要這樣寫:

public class PlayGame {
    public static void main(String [] a) {
        King kevingo = new King();
        kevingo.setFightAction(new KnifeBehavior());
        kevingo.fight();

        Queen mary = new Queen();
        mary.setFightAction(new SwordBehavior());
        mary.fight();

        Knight tom = new Knight();
        tom.setFightAction(new KnifeBehavior());
        tom.fight();
    }
}


往後,當我們需要有新的攻擊方式時,只需要重新建立一個新的攻擊類別,而如果皇后要改拿其他的武器時,也只要在setFightAction中指定新的攻擊類別,真是太好了!

再回顧一下Strategy Pattern的定義:

  • 策略模式在於觀察程式中變動的部分,並且將他們抽離出來封裝成可互相抽換的演算法家族。這個模式讓你即使任意更換實作的演算法,也不會變動到去使用者他們的客戶端程式。

在這個範例中,我們把不同型態的攻擊方法抽出來變成一組家族,建立一個Interface叫做Attack,同時根據不同的攻擊方法來建立不同的類別,往後我們只要利用set方法就可以輕鬆的替換攻擊的方式,這就是策略模式的用途所在。

當然這個模式不是沒有缺點,最顯而易見缺點就是他必須要維護比較多的類別,當實作的策略變多的時候,維護起來就會比較吃力囉。

Share this post!

Bookmark and Share

0 意見: