設計之禪——靈活的策略模式

一、引言

在平時生活中當我們想要做一件事的時候往往會有許多的途徑和方法,像我們去公司上班,可以走路去,也可以騎車或者開車去;還有像吃飯,我們可以選擇自己做飯吃,也可以出去吃,臉長得好看的還能讓人請吃飯等等,但無論選擇哪種方式,我們最終達到的目的結果都是一樣的,只是過程不一樣。在面向對象的程序設計中,我們就可以把這種變化的行爲隔離封裝,實現代碼的高度擴展和複用,也就是我今天要講的策略模式。

二、什麼是策略模式

在探討策略模式之前,我們需要了解幾個OO原則:

  • 封裝變化
  • 多用組合,少用繼承
  • 針對接口編程,不針對實現編程

封裝變化不用多說,如果不從固有的代碼中將變化的代碼抽離出來,那將會讓程序變得非常臃腫;
那爲什麼要多用組合,少用繼承呢?繼承不是OO的基礎嗎?我們來看一個例子:假如有一隻綠頭鴨和紅頭鴨,他們都會跑,也都會叫,因此可以抽象出一個Duck類,有run和quack方法,看似沒有什麼問題,但是當某一天出現了一隻木頭鴨,它也需要繼承Duck類,但是它不會叫也不會跑啊,咋辦呢?當然,我們可以利用方法重寫,在子類中將父類的行爲覆蓋掉;這是一個方法,不過我們可能還會出現會飛的野鴨、火箭玩具鴨等等,怎麼辦呢?難道去修改父類,在父類中增加一個fly方法麼?那之前不會飛的鴨子也都可以滿天飛了,至此,我們看到了濫用繼承所帶來的困擾,也發現了鴨子的行爲對於鴨子來說是多變的,因此我們可以將鴨子的行爲抽象出來爲Behavior接口(也就是針對接口編程),並利用組合將行爲織入到鴨子中,就可以解決上述的問題了。這就是策略模式的核心,來看看《Head First》對其的定義:

策略模式定義了算法族,分別封裝起來,讓他們之間可以互相替換,此模式讓算法的變化獨立於使用算法的客戶。

三、代碼實現

瞭解了策略模式的定義,我們再來看看如何利用代碼實現該模式。想象一個冒險遊戲,將其分爲角色和武器行爲兩大類,角色可以更換任意一種武器來攻擊敵人。

public abstract class Character {

    WeaponBehavior weaponBehavior;

    public void setWeaponBehavior(WeaponBehavior weaponBehavior) {
        this.weaponBehavior = weaponBehavior;
    }

    public void fight() {
        weaponBehavior.userWeap();
    }

}

public class King extends Character {

    public King(WeaponBehavior weaponBehavior) {
        this.weaponBehavior = weaponBehavior;
    }

}

public interface WeaponBehavior {

    void userWeap();

}

public class SwordBehavior implements WeaponBehavior {

    @Override
    public void userWeap() {
        System.out.println("用寶劍揮舞!");
    }

}

public class KnifeBehavior implements WeaponBehavior {

    @Override
    public void userWeap() {
        System.out.println("用匕首刺殺");
    }

}
public static void main(String[] args) {
        Character c = new King(new AxeBehavior());
        c.fight();
        c.setWeaponBehavior(new SwordBehavior());
        c.fight();
    }

在父類角色中,利用組合將武器行爲賦予給角色,在角色攻擊時實際是將攻擊行爲委託給WeaponBehavior的,同時需要注意,這裏使用的是WeaponBehavior接口,而不是具體的某種武器,這樣我們在程序運行時需要使用哪種武器就只需要調用setter方法重新設置他需要的武器即可,這也就是針對接口編程,不針對實現編程

四、總結

策略模式非常的簡單,也非常的有用,可以將變化的算法從程序中解耦出來,在程序設計之初時,我們就可以仔細思考發現這部分變化,以便將來的擴展。但策略模式也不是完美的,客戶端需要知道所有的策略類以及區別,並自行選擇使用哪一種,同時也會造成大量的策略類和對象,導致系統結構越來越龐大,對象數量過多也會佔用大量的內存,可以使用享元模式來減少對象的數量。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章