Java 設計模式-策略模式(Strategy)Android講解

哲學上說存在即合理。一些初級程序員,包括筆者也曾經在內心說過:“XX這鳥毛東西有什麼用啊,根本就沒必要這麼做,真不知道爲什麼會有這東西”,就拿着這設計模式來說,以前接觸的時候總覺得好複雜,小小的功能要分好幾層,隨着項目經驗的積累,才發現這話說出來真的是打臉啊。是自己的無知導致狂妄的想法。
不是設計模式沒有用,而是你不會!(啊!又被打臉)
最近在寫SDK,架構項目,項目寫到一半,回頭看看,總覺得自己的代碼平平無奇。而且在一些優秀的開源框架中出現的代碼寫法,根本沒有用過。於是嘗試着看看開源代碼,突然發現原來同一種功能有這麼多種實現方式,而且覺得很帥。(所謂的很帥是個人的看法,作爲一個程序員,儘量不要寫出很挫的代碼,類似一個方法裏面有十幾個 if 語句,或者4,5個類中,一半的代碼是重複的,只是小部分代碼是變動的,那麼這時候,就應該停下來好好想想是不是自己代碼寫的有問題了,是不是還有更優秀的實現方式)。其實,代碼繁雜還是一回事,對沒有強迫症的人影響不大,但是,代碼擴展性不好,不易維護,那就是對所有人都是致命的了。簡直會讓人抓狂。
今天記錄一下 策略模式,博文作爲筆記記錄

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

什麼意思?別問我,我也不知道。臥槽,那學個毛線,算了,先看看在Android中什麼時候使用到了策略模式

listView.setAdapter(new BAdapter());

沒錯,所有Android程序員都是使用過的方法,對着這行代碼,試着理解一下策略模式的定義:

  • 定義了算法族,分別封裝起來

    new BAdapter() 繼承 BaseAdapter 具體算法在 getView 中實現。不同的Adapter繼承 BaseAdapter 實現自己的UI佈局,相當於定義了算法族,分別封裝起來。

  • 讓它們之間可相互替換

    new AAdapter()new BAdapter()new CAdapter() 對於這些一個個獨立封裝起來的算法,他們之間可以相互替換,被設置到 listView 中。

  • 此模式讓算法的變化獨立於使用算法的客戶

    這裏客戶是指這些算法的調用者 listView 。在A,B,CAdapter() 中的算法變化,完全獨立於 listView ,對於新增的算法,不用再使用 if 語句判斷該使用哪一種,客戶直接使用算法就可以,算法的實現也是獨立的。大大提高了程序的擴展性,和維護性。媽媽再也不用擔心我修改一個小功能導致4,5個類的代碼要修改了。

具體實現

在網上查閱資料的時候看到很多人以銷售商品是結算價格舉例,【輸入商品的價格和數量,得出總價,現在商店促銷搞活動,商品打折(7折,8折…),滿減(滿400立減40…)】,這裏拋磚引玉,具體看看代碼,這裏就不貼參考的連接了,如有雷同,純屬巧合。直接看代碼

  • 折扣方式接口,面向接口編程,保持了繼承的優點(代碼重用),比繼承更靈活(算法獨立,可以任意擴展)。
package cn.design.java.strategy;

public interface IDiscount {

    public double getPrice(double price, int quantity);

}
  • 折扣方式—打折,實現IDisCount,設置折扣值 setDiscount(double discount),(7折,8.8折,等等),重寫 getPrice(double price, int quantity) 方法實現折扣算法。
package cn.design.java.strategy;

/**
 * 折扣方式-打折
 * 
 * @author Ruffian
 * @date 2016年5月11日
 * 
 */
public class RebateDis implements IDiscount {

    // 折扣
    private double discount;

    public double getDiscount() {
        return discount;
    }

    public void setDiscount(double discount) {
        this.discount = discount;
    }

    @Override
    public double getPrice(double price, int quantity) {

        double sellPrice = price * quantity;

        if (discount > 0) {
            sellPrice = sellPrice * discount;
        }

        return sellPrice;
    }

}
  • 折扣方式—滿減,實現IDisCount,設置折扣消費條件 setCondition(int conditionMoney, int reduceMoney),(滿400立減40,等),重寫 getPrice(double price, int quantity) 方法實現折扣算法。
package cn.design.java.strategy;

/**
 * 折扣方式-滿減
 * 
 * @author Ruffian
 * @date 2016年5月11日
 * 
 */
public class ReduceDis implements IDiscount {

    // 滿減條件金額
    private int conditionMoney;
    // 立減金額
    private int reduceMoney;

    public void setCondition(int conditionMoney, int reduceMoney) {
        this.conditionMoney = conditionMoney;
        this.reduceMoney = reduceMoney;
    }

    @Override
    public double getPrice(double price, int quantity) {

        double sellPrice = price * quantity;

        if (sellPrice > conditionMoney) {
            sellPrice = sellPrice - reduceMoney;
        }

        return sellPrice;
    }
}
  • 客戶類
    基本的算法寫完了,接下來編寫一個客戶類,這裏相當於,編寫 listView 類,以及 setAdapter()
package cn.design.java.strategy;

/**
 * 客戶使用類-策略模式
 * 
 * @author Ruffian
 * @date 2016年5月11日
 * 
 */
public class DiscountStrategy {

    // 折扣方式
    private IDiscount discount;

    public void setDiscount(IDiscount discount) {
        this.discount = discount;
    }

    // 計算價格
    public void calculatePrice(double price, int quantity) {

        double sellPrice = price * quantity;
        String discountName = "default";

        if (discount != null) {
            discountName = discount.getClass().getName();
            sellPrice = discount.getPrice(price, quantity);
        }

        System.out.println("折扣方式: " + discountName + "  折後價格: " + sellPrice);

    }

}
  • 測試類
package cn.design.java.strategy;

public class Test {

    public static void main(String[] args) {

        // 折扣方式
        IDiscount reduceDis = new ReduceDis();
        IDiscount rebateDis = new RebateDis();
        DiscountStrategy discountStrategy = new DiscountStrategy();

        // 滿減(滿400立減40)
        ((ReduceDis) reduceDis).setCondition(400, 40);
        discountStrategy.setDiscount(reduceDis);
        discountStrategy.calculatePrice(138.5, 3);

        // 8.8折
        ((RebateDis) rebateDis).setDiscount(0.88);
        discountStrategy.setDiscount(rebateDis);
        discountStrategy.calculatePrice(138.5, 3);

        // default
        discountStrategy.setDiscount(null);
        discountStrategy.calculatePrice(138.5, 3);

    }
}
  • 打印結果

這裏寫圖片描述

一個流程測試下來了,有沒有發現 策略模式 有什麼奇妙的地方?當然有,多了去了!現在看看測試類,這裏我只需要將我需要打折的方式設置進去,就可以調用對應的折扣算法,每一種折扣方式的算法獨立,就算修改算法實現方式,不會影響到 客戶 的調用方式。這還不算什麼,假如客戶提出新的需求,添加一種新的折扣方式,沒問題,新增一種折扣類,實現算法,調用的時候,直接 new 然後 setDiscount() ,OK,搞定,完全不會影響到之前的代碼,哪怕之前的2種算法是誰寫的,完全不用去理會。

以上是筆者對 策略模式 的一點點理解,記錄下來當做筆記使用,如有不正之處,懇請指正出來,共同進步。

源碼下載

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