1. 程式人生 > >設計模式(四)【Strategy模式】

設計模式(四)【Strategy模式】

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、必須以相同的方式呼叫所有演算法(多型)
實現 讓使用演算法的類包含一個抽象類,抽象類有一個抽象方法指定如何呼叫演算法,子類按需求實現具體演算法。

參考《設計模式解析》第二版