時勢造英雄——策略模式
《Android原始碼設計模式解析與實戰》讀書筆記(七)
《Android原始碼設計模式解析與實戰》PDF資料下載一、策略模式的簡介
1.1、定義
策略模式定義了一系列的演算法,並將每一個演算法封裝起來,而且使它們還可以相互替換。策略模式讓演算法獨立於使用它的客戶而獨立變化。
1.2、使用場景
- 針對同一型別問題的多種處理方式,僅僅是具體行為有差別時;
- 需要安全地封裝多種同一型別的操作時。
- 出現同一抽象類有多個子類,而又需要使用if-else或者switch-case來選擇具體子類時。
二、策略模式的簡單實現
示例:公交車和地鐵的價格計算方式是不一樣的,需要計算乘不同出行工具的成本,下面是第一版的程式碼:
public class PriceCalculator { //公交車型別 private static final int BUS = 1; //地鐵型別 private static final int SUBWAY = 2; public static void main(String[] args) { PriceCalculator calculator = new PriceCalculator(); System.out.println("坐16公里的公交車票價為:" + calculator.calculatePrice(16, BUS)); System.out.println("坐16公里的地鐵票價為:" + calculator.calculatePrice(16, SUBWAY)); } /** * 北京公交車,十公里之內一元錢,超過十公里之後每加一元錢可以乘5公里 * * @param km * @return */ private int busPrice(int km) { //超過十公里的總距離 int extraTotal = km - 10; //超過的距離是5公里的倍數 int extraFactor = extraTotal / 5; //超過的距離對5公里取餘 int fraction = extraTotal % 5; //價格計算 int price = 1 + extraFactor * 1; return fraction > 0 ? ++price : price; } /** * 6公里(含)內3元;6~12公里(含)4元;12~22公里(含)5元;22~32公里(含)6元; * @param km * @return */ private int subwayPrice(int km) { if (km <= 6) { return 3; } else if (km > 6 && km <= 12) { return 4; } else if (km > 12 && km <= 22) { return 5; } else if (km > 22 && km <= 32) { return 6; } return 7; } int calculatePrice(int km, int type) { if (type == BUS) { return busPrice(km); } else if (type == SUBWAY) { return subwayPrice(km); } return 0; } }
輸出結果:

策略模式1.png
此時的程式碼已經比較混亂,各種if-else語句纏繞其中。當價格的計算方法變化時,需要直接修改這個類中的程式碼,很容易引入錯誤。
這類程式碼必然是難以應對變化的,它會使得程式碼變得越來越臃腫,難以維護。
用策略模式對上述示例進行重構:
/** * 計算介面 */ public interface CalculateStrategy { /** * 按距離來計算價格 * @param km * @return */ int calculatePrice(int km); }
//公交車價格計算策略 public class BusStrategy implements CalculateStrategy { /** * 北京公交車,十公里之內一元錢,超過十公里之後每加一元錢可以乘5公里 * @param km * @return */ @Override public int calculatePrice(int km) { //超過十公里的總距離 int extraTotal = km - 10; //超過的距離是5公里的倍數 int extraFactor = extraTotal / 5; //超過的距離對5公里取餘 int fraction = extraTotal % 5; //價格計算 int price = 1 + extraFactor * 1; return fraction > 0 ? ++price : price; } }
public class SubwayStrategy implements CalculateStrategy { @Override public int calculatePrice(int km) { if (km <= 6) { return 3; } else if (km > 6 && km <= 12) { return 4; } else if (km > 12 && km <= 22) { return 5; } else if (km > 22 && km <= 32) { return 6; } return 7; } }
再建立一個扮演Context角色的類
public class TranficCalculator { public static void main(String[] args) { TranficCalculator calculator = new TranficCalculator(); //設定計算策略 calculator.setStrategy(new BusStrategy()); //計算價格 System.out.println("坐16公里的公交車票價為:"+calculator.calculatePrice(16)); } CalculateStrategy mStrategy; public void setStrategy(CalculateStrategy mStrategy) { this.mStrategy = mStrategy; } public int calculatePrice(int km) { return mStrategy.calculatePrice(km); } }
這種方案在隱藏實現的同時,可擴充套件性變得很強。在簡化邏輯、結構的同時,增強了系統的可讀性、穩定性、可擴充套件性,這對於較為複雜的業務邏輯顯得更為直觀,擴充套件也更為方便。
三、總結
策略模式主要用來分離演算法,在相同的行為抽象下有不同的具體實現策略。這個模式很好地演示了開閉原則,也就是定義抽象,注入不同的實現,從而達到很好的可擴充套件性。
3.1、優點
- 結構清晰明瞭、使用簡單直觀;
- 耦合度相對而言較低,擴充套件方便;
- 操作封裝也更為徹底,資料更為安全。
3.2、缺點
- 隨著策略的增加,子類也會變得繁多。
學海無涯苦作舟

我的微信公眾號