Strategy模式
起源
Delphi的STRATEGY模式是在STRATEGY的基礎上進行了擴展。更多STRATEGY模式的資料請參閱《設計模式208頁》
目的
定義一系列的演算法,把它們一個個封裝起來,並且使它們可相互替換。本模式使得演算法可獨立於使用它的客戶面變化。
動機
? 由於需要可以動態的變換不同的策略。 ? 更好的封裝多個行為與演算法結構,而不讓客戶程式直接幹擾? 透過相關的條件語句選擇正確的行為方法。
Template方法使用繼承來變換部分演算法。 Strategies則使用代理和組合來變換所有的演算法並支援動態變換。以後,將使用context物件在運行期間動態的分配具體的演算法。同樣,透過使用context對象,客戶類別將從依賴的演算法介面中分離出來,透過context物件可以提供更多的泛化介面。同樣意義的是,透過
context與
strategy介面可以在將來設計並提供全系統的相關演算法來實現具體的應用而無需改變介面。
Strategies同樣讓你您建立單一的、間單的、易於維護的類別框架。類別框架依賴繼承。
應用
Implementation
下例中的對信用卡進行月利率進行計算。
Strategy模式透過充一的抽象類別TfinanzeCharge封裝、存取介面並擔供不同的演算法來進行月利率計算。 TregularCharge、TPReferredCharge為信用卡的月利率計算封裝了不同的具體演算法TmonthlyCharge實作了TcontextCharge介面並配置了不同的策略物件。 TconntextCharge成為客戶物件與策略物件的中場發動機,這樣有助於感輕客戶物件與策略/物件的依賴性。
//策略介面(抽象類別) TFinanzeCharge = class public // 回傳計算的結果
function getCharge(const Balance: double): double; virtual; abstract; end;
//具體策略TRegularCharge = class(TFinanzeCharge) public
function getCharge(constst Balance: double): double; override ; end;
//具體策略TPreferredCharge = class(TFinanzeCharge) public
function getCharge(const Balance: double): double; override; end;客戶程式依賴上下文介面來調度指定的策略。無論如何,因為上下文介面是為客戶程式而產生的,客戶程式必須知道可用的策略/物件。如果上下文無法傳回一個有效的實例,可選擇選擇預設策略的方法實作。
//上下文介面TChargeContext = class public
function ComputeCharges(const Balance: double): double; virtual; abstract ; end;
//具體上下文類別TmonthlyCharges作為客戶物件與策略物件的中場發動機,並透過在它的建構器傳遞一個具體的利率計算實例進行設定。
This class acts as a mediator between the client and the strategy classes, and is configured by using composition and passing an instance of a concrete finance charge in its constructor.
TMonthly ? Destroy; override; end;---implementation
// TRegularCharge function TRegularCharge.getCharge(const Balance: double): double;begin result := Balance * (REG_RATE / 12);end;
// TPreferredCharge function TPgetdredge. ): double;begin // this could be a complex algorithm that takes into account the // credit card holder's buying patterns and reward points accumulated. result := Balance * (PREFERRED_RATE / 12);end;
// Concrete Contextn TmoMonthlyCharges constructorm. begin inherited Create; // aFinanzeCharge configures the context object // this class takes ownership of aFinanzeCharge (will destroy it) FFinanzeCharge := aFinanzeCharge;end;destructor TMonthlyCharges.Destroym; TMonthlyCharges.ComputeCharges(const Balance: double): double;begin result := FFinanzeCharge.getCharge(Balance);end;
Delphi實例