策略模式屬於對象的行為模式。其用意是針對一組算法,將每一個算法封裝到具有共同接口的獨立的類中,從而使得它們可以相互替換。策略模式使得算法可以在不影響到客戶端的情況下發生變化。
本文地址:http://www.cnblogs.com/wuyudong/p/5924223.html,轉載請注明源地址。
策略模式是對算法的包裝,是把使用算法的責任和算法本身分割開來,委派給不同的對象管理。策略模式通常把一個系列的算法包裝到一系列的策略類裡面,作為一個抽象策略類的子類。用一句話來說,就是:“准備一組算法,並將每一個算法封裝起來,使得它們可以互換”。下面就以一個示意性的實現講解策略模式實例的結構。
這個模式涉及到三個角色:
● 環境(Context)角色:持有一個Strategy的引用。
● 抽象策略(Strategy)角色:這是一個抽象角色,通常由一個接口或抽象類實現。此角色給出所有的具體策略類所需的接口。
● 具體策略(ConcreteStrategy)角色:包裝了相關的算法或行為。
策略模式的使用場景:
1)針對同一種問題的多種處理方式、僅僅是因為具體行為有差別時,
2)需要安全的封裝多種同一類型的操作時
3)出現同一抽象類有多個子類,而又需要使用if-else或者switch-case來選擇具體子類時。
舉個例子,計算公交車和地鐵運行指定路程後所需的票價
package com.wuyudong.strategy.normal; 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("坐10公裡的公交車的票價為:" + calculator.calculatePrice(10, BUS)); System.out.println("坐10公裡的地鐵的票價為:" + calculator.calculatePrice(10, SUBWAY)); } //計算公交價格 private int busPrice(int km) { int extraTotal = km - 10; int extraFactor = extraTotal / 5; int fraction = extraTotal % 5; int price = 1 + extraFactor * 1; return fraction > 0 ? ++price : price; } //計算地鐵價格 private int subwayPrice(int km) { if (km <= 6) { return 3; } else if (km > 6 && km < 12) { return 4; } else if (km < 22 && km > 12) { return 5; } else if (km < 32 && km > 22) { return 6; } return 7; } //根據類型來計算相應的價格 private int calculatePrice(int km, int type) { if (type == BUS) { return busPrice(km); } else { return subwayPrice(km); } } }
如果再添加一種出租車的價格計算,添加相應的代碼:
public class PriceCalculator { // 公交車類型 private static final int BUS = 1; // 地鐵類型 private static final int SUBWAY = 2; // 出租車類型 private static final int TAXI = 3; public static void main(String[] args) { PriceCalculator calculator = new PriceCalculator(); System.out.println("坐10公裡的公交車的票價為:" + calculator.calculatePrice(10, BUS)); System.out.println("坐10公裡的地鐵的票價為:" + calculator.calculatePrice(10, SUBWAY)); } // 計算出租車價格 private int taxiprice(int km) { return km * 2; } // 根據類型來計算相應的價格 private int calculatePrice(int km, int type) { if (type == BUS) { return busPrice(km); } else if (type == SUBWAY) { return subwayPrice(km); } else { return taxiprice(km); } } }
可見上面的代碼耦合性較高,每當增加新的交通工具類型的時候,需要不斷的修改大量的代碼,這裡使用策略模式重構:
首先定義一個抽象的價格計算接口:
//計算接口 public interface CalculateStrategy { int calculatePrice(int km); }
每一種出行方式都定義一個獨立的計算策略類:
公交車計算策略
public class BusStrategy implements CalculateStrategy { public int calculatePrice(int km) { int extraTotal = km - 10; int extraFactor = extraTotal / 5; int fraction = extraTotal % 5; int price = 1 + extraFactor * 1; return fraction > 0 ? ++price : price; } }
地鐵計算策略
public class SubwayStrategy implements CalculateStrategy { public int calculatePrice(int km) { if (km <= 6) { return 3; } else if (km > 6 && km < 12) { return 4; } else if (km < 22 && km > 12) { return 5; } else if (km < 32 && km > 22) { return 6; } return 7; } }
再創建一個扮演Context的角色,代碼如下:
public class TranficCalculator { CalculateStrategy mStrategy; public static void main(String[] args) { TranficCalculator calculator = new TranficCalculator(); //設置計算策略 calculator.setStrategy(new BusStrategy()); //計算價格 System.out.println("公交車乘10公裡的價格:" + calculator.calculatePrice(10)); } public void setStrategy(CalculateStrategy mStrategy) { this.mStrategy = mStrategy; } public int calculatePrice(int km) { return mStrategy.calculatePrice(km); } }
這樣即使需要添加出租車的價格計算,只需要簡單的新建一個類,讓其繼承自CalculateStrategy接口並實現其中的方法即可
優點
1)結構清晰明了、使用簡單直觀
2)耦合度相對較低,擴展方便
3)操作封裝因為更為測地、數據更為安全
缺點
子類增多