策略模式是對演算法的封裝,把使用演算法的責任和演算法本身分隔開,委派給不同的對象管理。策略模式通常把一系列的演算法封裝到一系列的策略類裡面,作為一個抽象策略類的子類。
何時使用原則模式:
1) 如果在一個系統裡面有許多類,它們之間的區別僅在於它們的行為,那麼使用原則模式可以動態讓一個對象在許多行為中選擇一種行為。
2) 如果系統需要動態地在幾種演算法中選擇一種。那麼這些演算法可以封裝到一個個的具體演算法類裡面,而這些演算法類都是一個抽象演算法類的子類。換言之,這些具體演算法類均有統一的介面,由於多態性原則。用戶端可以選擇使用任何一個具體演算法類,並只持有一個資料類型是抽象演算法類的對象。
3) 一個系統的演算法使用的資料不可以讓用戶端知道。策略模式可以避免讓用戶端涉及到不必要接觸到的複發的和只與演算法有關的資料。
4) 假設這樣一個案例:假設現在要設計一個販賣各類書籍的電子商務網站的購物車系統。如果要計算購物車的貨品的價格,一個最簡單的情況就是把所有貨品的單價乘上數量,但是實際情況肯定比這要複雜。比如,教材類圖書每本一元折扣,連環畫類圖書每本7%的折扣,非教材類電腦圖書3%折扣,其餘沒有折扣。這個價格計算問題就可以由策略模式來解決。
類圖:
原始碼:
public class Context {
private Strategy stg;
public Context(Strategy theStg)
{
this.stg = theStg;
}
public void DoAction()
{
this.stg.AlgrithmInterface();
}
}
public class ConcreteStrategyA implements Strategy {
public void AlgrithmInterface()
{
System.out.println("ConcreteStrategyA.AlgrithmInterface");
}
}
public class ConcreteStrategyB implements Strategy {
public void AlgrithmInterface()
{
System.out.println("ConcreteStrategyB.AlgrithmInterface");
}
}
public class Context {
private Strategy stg;
public Context(Strategy theStg)
{
this.stg = theStg;
}
public void DoAction()
{
this.stg.AlgrithmInterface();
}
}
public class Client {
public static void main(String[] args) {
Strategy stgA = new ConcreteStrategyA();
Context ct = new Context(stgA);
ct.DoAction();
}
}
策略模式的缺點:
1) 用戶端必須知道所有的策略類,並自行決定使用哪一個策略類,這就意味著用戶端必須
理解這些演算法的區別,以便適時選擇恰當的演算法類。換言之,策略模式只適用於用戶端知道所有的演算法或行為的情況。
2)策略模式造成許多的策略類。有時候可以通過把依賴於環境的狀態儲存到用戶端裡面,而將策略類設計成可共用的,這樣策略類執行個體可以被不同用戶端使用。換言之,可以使用享元模式來減少對象的數量。