設計模式——策略模式

前言

很早就想系統學習一下設計模式,跟公司的大佬交流了下,知道了我現在手上這本書——《Head First設計模式》,在下班後就迫不及待開始翻書了。這是一本挺沙雕的書,跟我以前看的書很不一樣,四個字形容——圖文並茂。讀起來一點都不枯燥,挺有意思的一本書。
我在看這本書的時候,看到了一些非常重要的話,對於我這樣的Java初學者來說挺重要的。
設計原則一:找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起。
設計原則二:針對接口編程,而不是針對實現編程(“針對接口編程"真正的意思是"針對超類型編程”)。
設計原則三:多用組合,少用繼承。

介紹

本書的第一個設計模式就是策略模式,我以前都沒有注意到這個設計模式。先看看這個模式定義:策略模式定義了算法族,分別封裝起來,讓他們之間可以相互替換,此模式讓算法的變化獨立於使用算法的客戶。

在看之前記住一件事,程序在後面升級過程中的變化。

假如要做一套模擬鴨子的遊戲,需要鴨子們在多種場景下活動。我們第一個想法就是寫一個Duck超類,不同的鴨子去繼承這個方法。
Version-1.0.0

public abstract class Duck {

    public void swimng(){
        System.out.println("swiming");
    }
    public abstract void quack(){
        System.out.println("GaGaGa!!!");
    }
    //鴨子的外觀
    public abstract void diaplay();
}

通過繼承Duck這個超類,不同外觀的鴨子就可以實現飛行和鳴叫。

Version-1.1.0

所有的鴨子都會鳴叫和游泳,但是飛行不是所有的鴨子都會的技能,現在要求加入一些會飛行的鴨子。
在原先版本上進行修改的話,對超類Duck修改成:

public abstract class Duck {

    public void swimng() {
        System.out.println("swimng");
    }

    public abstract void quack() {
        System.out.println("GaGaGa!!!");
    }
    //添加飛行方法
    public abstract void fly();
    
    public abstract void diaplay();
}

對於會飛的鴨子,我們只需要覆寫fly( ),對於不會飛的鴨子,不用實現其方法體。

Version-1.2.0
現在遊戲進行大升級,要求加入洗澡玩的橡皮鴨。考慮下橡皮鴨的特性,橡皮鴨不會叫。如果你硬要說橡皮鴨被擠壓的時候會叫,那我們就加入木頭做的鴨子,這回總不會叫了。
現在思考超類Duck中的quack( ),裏面已經寫了方法體。要是還想繼續用Duck這個超類,你可以將quack( )方法寫成抽象方法,並在子類裏面實現quack( )方法。如果前面寫了很多鴨子了,工程量非常龐大,而且隨着加入新鴨子的特性,任務量只會越來越誇張。
現在考慮使用接口的方法實現,將鴨子的swiming( )、display( )方法提取出來作爲抽象類,Fly( )和quack( )方法抽出來作爲接口,鴨子們只需繼承超類Duck和實現需要的接口即可。

public abstract class Duck {
    public void swimng() {
        System.out.println("swimng");
    }
    public abstract void display();
}

public interface Flyable {

    void fly();
}
public interface Quakable {
    
    void quack();
}

思考?

子類實現接口中的方法時,出現了大量重複的方法。 可以通過什麼樣的方法,能提高代碼的複用率。在上面的例子中,我們已經得出了一種辦法,就是將不需要變化和易變的分開處理。現在可以回到介紹那塊看下策略模式的定義。

策略模式

個人認爲策略模式很重要的一點是多態
首先,在Duck類中加入Quackable和Flyable這個兩個接口的實例變量,子類就不需要實現接口中的方法,只需要調用setFlyable(Quackable quack)和setQuakable(Flyable fly)方法就可以調用對應的方法,這樣就提高了代碼的複用率。
代碼:

public abstract class Duck {

    private Flyable flyable;
    private Quakable quakable;

    public void swimng() {
        System.out.println("swimng");
    }

    public abstract void display();

    public void fly() {
        flyable.fly();
    }

    public void quack() {
        quakable.quack();
    }
	//getter setter
}
public interface Flyable {

    void fly();
}
``

public interface Quakable {

void quack();

}
``

public class FlySnow implements Flyable {

    @Override
    public void fly() {
        System.out.println("Snow Fly");
    }
}
public interface Quakable {

    void quack();
}
public class FlySnow implements Flyable {

    @Override
    public void fly() {
        System.out.println("Snow Fly");
    }
}
public class GaGaGa implements Quakable {
    @Override
    public void quack() {
        System.out.println("GaGaGa!!!");
    }
}
public class NewDuck extends Duck {
    
    Flyable flyable = new FlySnow();
    Quakable quakable = new GaGaGa();

    public NewDuck() {
        this.setFlyable(flyable);
        this.setQuakable(quakable);
    }
    
    @Override
    public void display() {
        System.out.println("白色的鴨子");
    }

}
public class Main {
    public static void main(String[] args) {
        Duck duck = new NewDuck();
        duck.quack();
        duck.fly();
        duck.display();
        duck.swimng();
    }
}

在這裏插入圖片描述
這本書的第一個設計模式就算結束了,相信你們看到這裏也覺得很迷糊,但是個人認爲重要的是這個思想。通過多態的特性,在運行時才能知道調用是哪一個具體的行爲。

內容肯定不止這些,等功力再次上升繼續更新!

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