設計模式(四)【Strategy模式】
阿新 • • 發佈:2019-01-12
Strategy模式
《設計模式》中的三個原則:
1、針對介面程式設計而不是實現
2、優先使用物件組合而不是類繼承
3、考慮設計中哪些是可變的,對變化的概念進行封裝。
例:國際電子商務系統案列研究
1、最初需求
系統處理來自不同國家的訂單。總框架中有一個控制器TaskController物件,處理銷售請求時,將請求轉發給SalesOrder物件進行處理。
SalesOrder物件的功能包括:
1、允許顧客通過GUI填寫訂單;
2、處理稅額計算;
3、處理訂單,列印銷售收據
有些功能要藉助其他物件實現。比如SalesOrder物件沒有必要自己列印,它的作用是充當一個存放銷售訂單的容器。具體的SalesOrder物件可以呼叫SalesTicket物件來列印。
2、處理新需求
需要修改處理稅額的方法。比如處理美國以外的客戶的訂單稅額。
一般來說處理概念相同但不同實現的任務有哪些方案?
- 複製貼上【×,不利於修改和debug】
- switch和if【×,條件或情況太多則不適用】
- 函式指標或委託【×,C++中的函式指標和C#的委託,但是無法維持每個物件的狀態,使用受限】
- 繼承(子類用新的方式處理)【×,太深的繼承層次導致多概念耦合(這裡的繼承指直接把包含需要改變的功能的類整個使用繼承)】
- 將整個功能委託給新的物件
遵循開頭列出的三個原則,應該這樣做:
1、尋找變化,並將它封裝到一個單獨的類中
2、將這個類包含在另一個類中
建立CalcTax物件,為完成稅額計算定義介面,由它派生所需的特定版本。
此處我把原書上的程式碼按自己的理解微調了一下。
public class TaskController{
private CalcTax myTax;//根據使用者GUI填寫資訊設定myTax到底是USTax還是CanTax,如果這個引數是直接和SalesOrder打交道的話,直接轉到SalesOrder裡即可。
private SalesOrder so;
public void process(){
so.calcTax(myTax,itemSold,qty,price);//資訊都由GUI得到
}
}
public class SalseOrder{
pubic double calcTax(CalcTax myTax,Salable itemSold, int qty, double price){
myTax.taxAmount(itemSold, qty, price);
}
public abstract class CalcTax{
abstract public double taxAmount(Salable itemSold, int qty, double price);
}
public class CanTax extends CalcTax{
public double taxAmount(Salable itemSold, int qty, double price){
//some code
}
}
public class USTax extends CalcTax{
public double taxAmount(Salable itemSold, int qty, double price)
//some code
}
這樣我們就不必要用繼承實現SalesOrder的多型,而只要實現變化部分的多型。
Strategy模式
定義一系列的演算法,把它們一個個封裝起來,並且使它們可互相替換,Strategy模式使演算法可獨立於使用它的客戶而變化。
Strategy模式以下列幾條原則為基礎:
1、物件具有職責
2、職責的不同實現是通過多型完成的
3、概念上相同的演算法不同的實現,需要進行管理
Strategy模式 | 關鍵特徵 |
---|---|
意圖 | 可以根據上下文使用不同的業務規則或演算法 |
問題 | 對於所需的演算法取決於發請求的使用者或者要處理的資料。如果是固定不變的演算法就不需要使用 |
解決方案 | 對於演算法的選擇和演算法的實現相分離。允許根據上下文進行選擇。 |
參與者與協作者 | 1、Strategy指定了如何使用不同的演算法 2、各ConcreteStrategy實現了這些不同的演算法 3、Context通過型別為Strategy的引用使用具體的ConcreteStrategy。Strategy與Context(可以看做獲得GUI的資料)相互作用以實現所需演算法。Context將來自使用者的請求轉發給Strategy。 |
效果 | 1、Strategy模式定義了一系列的演算法 2、可以不使用switch和if 3、必須以相同的方式呼叫所有演算法(多型) |
實現 | 讓使用演算法的類包含一個抽象類,抽象類有一個抽象方法指定如何呼叫演算法,子類按需求實現具體演算法。 |
參考《設計模式解析》第二版