設計模式之策略模式--慕課網筆記

第1章 引子:什麼是策略模式
1-1 策略模式簡介
  1. 什麼是策略模式
  2. 策略模式如何實現
  3. 策略模式總結篇
  4. 實際案例分享

日常生活中的例子:

  • 文本編輯軟件–》佈局 –》佈局算法
    • 算法實現1
    • 算法實現2
    • 算法實現3
  • 購物–》支付–》支付算法
    • 招商銀行
    • 建設銀行
    • XXX銀行

共同點:

  • 抽象出不變部分
  • 定義算法族分別封裝起來
  • 客戶端不會受算法改變的影響
  • 對新增需求彈性的支持

策略模式將可變的部分從程序中抽象分離成算法接口,在改接口下分別
封裝一系列算法實現並使他們可以相互替換,從而導致客戶端程序獨立
獨立於算法的改變。

第2章 光榮與夢想——鴨子應用:策略模式的實現
2-1 光榮與夢想:模擬應用背景介紹

光榮與夢想:鴨子應用

  • 飛行的能力
  • 更多類型的鴨子
  • 每六個月發佈一款產品

  • 鴨子的鳴叫

  • 鴨子的顯示
  • 原有的功能
  • 飛行的能力
2-2 求索之路:鴨子如何才能飛

原有代碼

/*
 * 超類,所有的鴨子都要繼承此類
 * 抽象了鴨子的行爲:顯示和鳴叫
 */
public abstract class Duck {

    /*
     * 鴨子發出叫聲
     * 通用行爲,由超類實現
     */
    public void quack(){
        System.out.println("嘎嘎嘎");
    }

    /*
     * 顯示鴨子的外觀
     * 鴨子的外觀各不相同,聲明爲abstract, 由子類實現
     */
    public abstract void display();



}
public class MallardDuck extends Duck {


    public MallardDuck(){
        super();
    }

    @Override
    public void display() {
        System.out.println("我的脖子是綠色的");
    }

}
public class RedheadDuck extends Duck {

    public RedheadDuck(){
        super();
    }

    @Override
    public void display() {
        System.out.println("我的頭是紅色的");
    }

}

讓我們的鴨子飛起來
方案一:
在父類中提供實現方法,子類通過繼承獲得父類中的飛行行爲

public void fly(){
    System.out.println("用翅膀飛行");
}
  • 優點
    • 簡(cu)單(bao)易(chou)用(lou),已有應用可以快速添加飛行的能力
  • 缺點
    • 不具有靈活性,對未來變更支持差。
    • 需要通過在子類中覆寫飛行的方法以提供新的飛行行爲。這很容易造成錯誤(粗心的程序員忘記覆寫)。

方案二:抽象方法
在父類中提供抽象方法,強迫子類實現自己的飛行行爲

public abstract void fly();
  • 優點
    • 足夠靈活。
    • 小夥伴再也不會忘記覆寫代碼了。
  • 缺點
    • 累死小夥伴了。
    • 每個子類都要實現一遍代碼,及時是相同的行爲也不例外。
    • 代碼重複,沒有複用代碼。
2-3 柳暗花明:策略讓鴨子飛上天

集成是重用代碼的利器
但繼承並不總是最好的工具

Favor composition over inheritace ———— Effective Java
複合優先與繼承
多用組合,少用繼承

面向對象 組合
Car has-a Tyre
汽車通過使用輪胎獲得輪胎的能力

在類中增加一個私有域,引用另一個已有的類的實例,通過調
用引用實例的方法從而獲得新的功能,這種設計被稱作組合(複合)。

方案三:組合
將飛行行爲抽象爲接口,在父類中持有該接口,並由該接口代理飛行行爲。

public interface FlyingStragety{
    void performFly();
}
private FlyingStragety flyingStragety;

public void fly(){
    flyingStragety.performFly();
}
  • 優點
    • 足夠靈活。
    • 複用代碼,更易於維護。
  • 缺點
    • 見第三章總結中缺點
2-4 腳踏實地:用代碼放飛鴨子
/*
 * 策略接口,實現鴨子的飛行行爲
 */
public interface FlyingStragety {

    void performFly();
}
/*
 * 超類,所有的鴨子都要繼承此類
 * 抽象了鴨子的行爲:顯示和鳴叫
 */
public abstract class Duck {

    /*
     * 鴨子發出叫聲
     * 通用行爲,由超類實現
     */
    public void quack(){
        System.out.println("嘎嘎嘎");
    }

    /*
     * 顯示鴨子的外觀
     * 鴨子的外觀各不相同,聲明爲abstract, 由子類實現
     */
    public abstract void display();


    private FlyingStragety flyingStragety;


    public void setFlyingStragety(FlyingStragety flyingStragety) {
        this.flyingStragety = flyingStragety;
    }

    public void fly(){
        flyingStragety.performFly();
    }


}
public class FlyWithWin implements FlyingStragety {

    public void performFly() {
        System.out.println("振翅高飛");
    }

}
public class MallardDuck extends Duck {


    public MallardDuck(){
        super();
        super.setFlyingStragety(new FlyWithWin());
    }

    @Override
    public void display() {
        System.out.println("我的脖子是綠色的");
    }

}
public class RedheadDuck extends Duck {

    public RedheadDuck(){
        super();
        super.setFlyingStragety(new FlyWithWin());
    }

    @Override
    public void display() {
        System.out.println("我的頭是紅色的");
    }

}
public class DuckTest {

    public static void main(String[] args){
        System.out.println("測試鴨子程序");
        System.out.println("************************");
        Duck duck = null;
//      duck = new MallardDuck();
        duck = new RedheadDuck();

        duck.display();
        duck.quack();
        duck.fly();
        System.out.println("************************");
        System.out.println("測試完畢");
    }

}
2-5 擁抱變化:用策略模式提供高複用性代碼

新加兩款產品,不能飛行

public class FlyNoWay implements FlyingStragety {

    public void performFly() {
        System.out.println("我不會飛行!");
    }

}
public class RubberDuck extends Duck {

    public RubberDuck() {
        super();
        super.setFlyingStragety(new FlyNoWay());
    }

    @Override
    public void display() {
        System.out.println("我全身發黃,嘴巴很紅");
    }


    public void quack(){
        System.out.println("嘎~嘎~嘎~");
    }

}
public class BigYellow extends Duck {

    public BigYellow() {
        super();
        super.setFlyingStragety(new FlyNoWay());
    }

    @Override
    public void display() {
        System.out.println("我身體很大,全身黃黃");
    }

}
2-6 萬變不離其宗:向宇宙進軍

新增太空鴨

public class FlyWithRocket implements FlyingStragety {

    public void performFly() {
        System.out.println("用火箭在太空遨遊");
    }

}
public class SpaceDuck extends Duck {

    public SpaceDuck() {
        super();
        super.setFlyingStragety(new FlyWithRocket());
    }

    @Override
    public void display() {
        System.out.println("我頭戴宇航頭盔");
    }

    public void quack(){
        System.out.println("我通過無線電與你通信");
    }

}

橡膠鴨、大黃鴨
- 代碼複用
太空鴨
- 更換策略模式

一生二,二生三,三生無窮!

第3章 總結篇
3-1 知識點總結

策略模式中的設計原則

  • 找出應用中需要變化的部分,把他們獨立出來,不要和那些不需要變化的代碼混在一起。
  • 面向接口編程,而不是面向實現編程。
  • 多用組合,少用繼承。

策略模式的實現

  1. 通過分離變化得出的策略接口Strategy
  2. Strategy的實現類
  3. 客戶程序“有一個”Strategy
  4. 在客戶程序中選擇/組裝正確的Strategy實現

策略模式的優點

  • 使用了組合,使架構更加靈活
  • 富有彈性,可以較好的應對變化(開—閉原則)
  • 更好的代碼複用性(相對於繼承)
  • 消除大量的條件語句

策略模式的缺點

  • 客戶代碼需要了解每個策略實現的細節
  • 增加了對象的數目

策略模式的適用場景

  • 許多相關的類僅僅是行爲差異
  • 運行時選取不同的算法變體
  • 通過條件語句在多個分支中選取一

《模式的祕密–策略模式》視頻地址

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