設計模式之禪(1)-策略模式


更多關於設計模式的文章請點擊設計模式之禪(0)-目錄頁


一、進一步的改進

上面的動物園例子似乎已經足夠地完善了,但是仔細想想並不是這樣:當另一個SmallDog被創建時,它實現了BarkBehavior接口,但是它需要在自身的代碼中去重寫這個bark()方法,這個bark()方法的具體實現暴露在了SmallDog類中,當我們需要修改SmallDogbark()方法實現時,我們需要在這個類中去修改代碼,這就造成了硬編碼問題,那麼應該怎麼解決呢?

這裏引申出策略模式的一個重要思想:使用組合,而不是實現

  • BigDogBark實現類
/**
 * @Auther: ARong
 * @Date: 2018/11/17 23:10
 * @Description:
 */
public class BigDogBark implements BarkBehavior {

    @Override
    public void bark() {
        System.out.println("Big Dog 汪汪汪...");
    }
}
  • BigDog可修改爲
/**
 * @Auther: ARong
 * @Date: 2018/11/17 11:09
 * @Description: com.iteason.Animal.BigDog 繼承 Animal的所有屬性和方法並實現BarkBehavior
 */
public class BigDog extends Animal {
    private BarkBehavior barkBehavior;

    //構造方法
    public BigDog(String name) {
        super(name);
        //在運行時將BigDogBark向上轉型爲BarkBehavior
        barkBehavior = new BigDogBark();
    }
    public BigDog() {
    }

    //將bark()方法的具體實現委託給BarkBehavior的子類
    public void performBark(){
        barkBehavior.bark();
    }


    public BarkBehavior getBarkBehavior() {
        return barkBehavior;
    }

    public void setBarkBehavior(BarkBehavior barkBehavior) {
        this.barkBehavior = barkBehavior;
    }
}

BigDog類中組合了一個BarkBehavior的接口,在構造方法中新建一個BarkBehavior的實現類BigDogBark通過面向對象的特徵:多態,在運行時確定由誰實現了BarkBehavior接口,並且將執行動作委託給了performBark()方法去調用barkBehavior.bark(),這就是一個簡單的策略模式的應用了。

以上關係可用UML關係圖來表達:
在這裏插入圖片描述

二、用策略模式組織類關係實例

在下面,你將看到一堆雜亂的類與接口,這是取自一個動作冒險遊戲。你將看到代
表遊戲角色的類,以及武器行爲的類。每個角色一次只能使用一個武器,但是可以
在遊戲的過程中換武器。你的工作是要弄清楚這一切…

這是HeadFirst設計模式中的一個問題,可以使用策略模式,畫出一個UML圖來表示他們的關係:用Character作爲角色的超類,裏邊含有角色的共同屬性以及可變的戰鬥武器接口、戰鬥模式接口對象;FightBehavior是戰鬥模式的接口,Quene和Random分別實現了隊列戰鬥模式和隨機戰鬥模式;WeaponBehavior是戰鬥武器接口,KnifeBehavior和GanBehavior分別是使用劍、槍作爲武器。

在這裏插入圖片描述
* Character超類

/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:35
 * @Description: 角色超類,定義了角色的名字和武器使用方式以及戰鬥行爲
 */
public abstract class Character {
    //角色名字
    private String name;

    //武器使用方式
    private WeaponBehavior weaponBehavior;

    //戰鬥行爲
    private FightBehavior fightBehavior;

 

    //構造方法
    public Character(String name) {
        this.name = name;
    }

    public Character() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public WeaponBehavior getWeaponBehavior() {
        return weaponBehavior;
    }

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

    public FightBehavior getFightBehavior() {
        return fightBehavior;
    }

    public void setFightBehavior(FightBehavior fightBehavior) {
        this.fightBehavior = fightBehavior;
    }
}
  • WeaponBehavior接口
/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:37
 * @Description: 定義了角色的武器使用方式
 */
public interface WeaponBehavior {
    public void userWeapon();
}
  • FightBehavior接口
/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:38
 * @Description: 定義了角色的戰鬥行爲
 */
public interface FightBehavior {
    public void fight();
}
  • KnifeBehavior實現類
/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:42
 * @Description: WeaponBehavior的實現類,使用劍作爲武器
 */
public class KnifeBehavior implements WeaponBehavior{

    @Override
    public void userWeapon() {
        System.out.println("使用劍戰鬥");
    }
}
  • GanBehavior實現類
/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:43
 * @Description: WeaponBehavior的實現類,使用槍作爲武器
 */
public class GanBehavior implements WeaponBehavior{

    @Override
    public void userWeapon() {
        System.out.println("使用槍戰鬥");
    }
}
  • Quene實現類
/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:40
 * @Description: FightBehavior的實現類,使用隊列戰鬥行爲
 */
public class Quene implements FightBehavior{

    @Override
    public void fight() {
        System.out.println("隊列戰鬥");
    }
}
  • Random實現類
/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:42
 * @Description: FightBehavior的實現類,使用隨機戰鬥行爲
 */
public class Random implements FightBehavior{
    @Override
    public void fight() {
        System.out.println("隨機戰鬥");
    }
}
  • GanFighter角色類
/**
 * @Auther: ARong
 * @Date: 2018/11/17 17:01
 * @Description: GanFighter是一個使用槍和隨機戰鬥方式的角色
 */
public class GanFighter extends Character{

    //構造方法
    public GanFighter(String name){
        super.setName(name);
        super.setWeaponBehavior(new GanBehavior());
        super.setFightBehavior(new Random());
    }

    public GanFighter(){

    }


    //使用武器
    public void performWeapon(){
        super.getWeaponBehavior().userWeapon();
    }

    //戰鬥方式
    public void performFight(){
        super.getFightBehavior().fight();
    }

}

GanFight是一個使用槍和隨機戰鬥方式的角色,所以在它的構造方法中,爲它的戰鬥武器和方式接口創建了具體的實現類,使他擁有了以槍爲武器和隨機戰鬥的方式。

使用GanFighter類:

@Test
    public void userGanFighter(){
        GanFighter g_fighter = new GanFighter("G_Fighter");

        System.out.println(g_fighter.getName());
        g_fighter.performWeapon();
        g_fighter.performFight();
    }

在這裏插入圖片描述

如果你想讓角色能更加地方便創建和使用,可以在使用方法時傳遞接口實現類的方式,從而達到要求:

/**
 * @Auther: ARong
 * @Date: 2018/11/17 16:44
 * @Description: Fighter類是Character的子類,並且在構造方法中需要實例化WeaponBehavior接口和FightBehavior接口的子類
 */
public class Fighter extends Character{
    //構造方法
    public Fighter(String n){
        //在實例化Fighter時指定Fighter的名字
        super.setName(n);
    }

    public Fighter(){

    }

    //戰鬥武器
    public void performWeapon(WeaponBehavior w){
        super.setWeaponBehavior(w);
        super.getWeaponBehavior().userWeapon();
    }

    //戰鬥方式
    public void performFight(FightBehavior f){
        super.setFightBehavior(f);
        super.getFightBehavior().fight();
    }

}

使用Fighter類去創建一個使用劍和隨機戰鬥方式的角色:

@Test
    public void userFighter(){

       Fighter ganFighter = new Fighter("劍神");

        System.out.println(ganFighter.getName());
        //使用劍
        ganFighter.performWeapon(new KnifeBehavior());
        //隨機戰鬥方式
        ganFighter.performFight(new Random());
    }

運行結果:
在這裏插入圖片描述

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