策略模式屬於對象的行為模式。其用意是針對一組算法,將每一個算法封裝到具有共同接口的獨立的類中,從而使得它們可以相互替換。策略模式使得算法可以在不影響到客戶端的情況下發生變化。
本文地址: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)操作封裝因為更為測地、數據更為安全
缺點
子類增多