Delphi模式程式設計之策略模式
劉藝
1.1 模式解說
策略(Strategy)模式的用意是定義一組演算法(algorithms),並將每個演算法封裝到具有共同介面的獨立的類別中,從而使它們可以相互替換。策略模式讓演算法變化獨立於使用它的客戶端。要了解策略模式的使用動機和意義,我們得先從一個有趣的例子說起。在一個物料管理系統中,出庫和入庫模組是這個系統的核心部分(以下我們以出庫為例進行分析)。對於一個沒有物件導向程式設計經驗的程式設計師,他們往往會把出庫的所有邏輯都放在客戶端(出庫單一介面),並在客戶端利用條件分支語句來判斷該出庫單類型是領料、借料或報損,以便選擇不同的出庫結算方法,如圖1‑1所示。這樣一來,客戶端的程式碼就變得複雜且難以維護。例如:需要新增調撥單類型的出庫時,就要修改判斷條件,重新編譯發布客戶端。當情況愈來愈複雜,條件分支會愈來愈多,添加的程式碼也會愈來愈多,這樣讓客戶端愈來愈大並難以維護,互相影響和出錯的可能性增大。圖1‑1 基於過程導向設計的出庫模組如果用物件導向的想法來分析,可以把領料單、借料單、報損單看成是出庫單的衍生類,如圖1‑2所示。這樣出庫單作為單據基類別提供單據的共同接口,而利用繼承的辦法在子類別裡實現不同的出庫行為。這實際上利用了物件導向裡的一個重要概念:多型態。但這樣的設計還有美中不足的地方,這就是環境和行為緊密耦合在一起。也就是說,單據和具體出庫的演算法緊密耦合在一起。強耦合使得兩者無法獨立演化,限制了重複使用性和擴展性。圖1‑3是利用策略模式重新設計的出庫模組。出庫單據物件透過一個出庫操作物件(即策略模式中的Context)來引用出庫策略物件。各種具體的出庫策略則由出庫策略類別的衍生類別實作。出庫單據可以由出庫操作和單據樣式分別提供出庫結算方法和單據顯示介面。這樣,策略模式就把出庫的行為從出庫單據的環境獨立出來,出庫演算法的增減、修改都不會影響到環境和客戶端。圖1‑2基於物件導向想法設計的出庫模組圖1‑3基於設計模式思想設計的出庫模組策略模式的優點在於演算法和環境的分離,兩者可以獨立演化。為了更好地說明演算法和環境分離的好處,我們不妨來看看圖1‑4的設計。在這個設計中,已經沒有出庫和入庫模組的概念,因為我將所有出/入庫單據抽像出來,在運行期動態組合單據的介面和行為。透過出/入庫操作類,可以維護、查詢、配置不同的行為類。抽象的出/入庫行為以策略類別的方式封裝了其對應的演算法,以便完成不同類型的出入庫單據的操作。這就顯而易見地提高了系統的重用性和可擴展性,並降低維護的難度。圖1‑4 策略模式的優點在於演算法和環境的分離,兩者可以獨立演化由此可見,策略模式適用於以下情況: · 當許多相關的類別之間的差異只在於其行為時。策略模式可以動態地讓一個物件在許多行為中選擇一種行為。 · 當實作一個目的有多種可選演算法時,例如:你出於不同的利弊權衡考慮定義的那些演算法(即相當於應用不同的策略)。這些具體的演算法可以封裝成抽象演算法類別的衍生類,並享受該抽象演算法類別的統一介面。透過多型性,客戶端只要持有一個抽象演算法類別的對象,就可以選用任何一個具體的演算法。 · 當一個演算法使用的資料不可以讓客戶端得知。使用策略模式可以避免暴露複雜的與演算法相關的資料結構。其實客戶端也沒有必要知道這些與演算法相關的知識和數據。 · 當一個類別定義有很多行為,並且用多個條件語句來判斷選擇這些行為。策略模式可以把這些行為轉移到對應的具體策略類別中,從而避免了難以維護的多重條件選擇,體現了物件導向的程式設計想法。
1.2 結構與用法
策略模式的結構如圖1‑5所示,它包括了以下參與者:· 抽象策略(TStrategy)-為所有支援的演算法聲明一個共同的介面。 TContext使用這個介面來呼叫由TConcreteStrategy定義和封裝的演算法。 · 具體策略(TConcreteStrategy)-封裝了具體演算法或行為。實作TStrategy介面。 · 上下文(TContext)-持有一個到TStrategy的引用。呼叫TStrategy接口,動態配置具體演算法或行為。圖1‑5策略模式的結構在策略模式中,透過TStrategy和TContext的交互實現所選擇的演算法。當演算法被呼叫時, TContext可以將該演算法所需的所有資料都傳遞給該TStrategy。或者,TContext可以將自己作為一個參數傳遞給TStrategy操作。當TContext將客戶端請求轉發給它的TStrategy時,客戶通常會建立並傳遞一個TConcreteStrategy物件給該TContext;這樣, 客戶端僅與TContext互動。通常有一系列的TConcreteStrategy類別可供客戶端從中選擇。 -------------------------------------------------- -----------------------------------------
更多相關文章和範例程式原始碼可以到作者網站下載:http://www.liu-yi.net