2011-05-04 105 views
5

我試圖將戰略模式應用於特定情況,但是在如何避免將每個具體策略耦合到爲其提供數據的上下文對象方面存在問題。以下是幾種不同方式發生的模式的簡化情況,但應以類似的方式處理。避免與策略模式耦合

我們有一個對象Acquisition,它提供了與特定時間框架相關的數據 - 基本上是使用不同的硬件收集的一堆外部數據。由於它包含的數據量太大,所以我不想承擔任何進一步的責任。我們現在需要採集一些這些數據,並根據一些配置向一塊硬件發送相應的電壓。

所以,想象一下以下(大大簡化)類:

class Acquisition 
{ 
    public Int32 IntegrationTime { get; set; } 
    public Double Battery { get; set; } 
    public Double Signal { get; set; } 
} 

interface IAnalogOutputter 
{ 
    double getVoltage(Acquisition acq); 
} 

class BatteryAnalogOutputter : IAnalogOutputter 
{ 
    double getVoltage(Acquisition acq) 
    { 
     return acq.Battery; 
    } 
} 

現在,每一個具體的策略類必須被連接到我的採集類,這也是最有可能的類別之一,因爲要修改它是我們應用程序的核心。這仍然是對舊設計的改進,這是一個巨大的開關語句裏面的Acquisition類。每種類型的數據可能有不同的轉換方法(雖然Battery是一個簡單的轉接,其他轉換方式並不那麼簡單),所以我覺得戰略模式或類似的應該是一條路。

我也會注意到在最後的實現中,IAnalogOutputter將是一個抽象類而不是接口。這些類將位於用戶可配置並序列化爲XML文件的列表中。該列表必須在運行時可編輯並記住,所以Serializable必須是我們最終解決方案的一部分。如果它有所作爲。

我該如何確保每個實現類都能獲得所需的數據,而無需將它綁定到我最重要的類之一上?還是我以完全錯誤的方式處理這類問題?

回答

0

好吧,我討厭這裏不是給別人的功勞,但我發現效果非常好,我的目的的混合解決方案。它完美的序列化,並大大簡化了新的輸出類型的添加。關鍵是一個界面,IOutputValueProvider。還要注意這種模式如何輕鬆處理檢索存儲數據的各種方法(如Dictionary而不是參數)。

interface IOutputValueProvider 
{ 
    Double GetBattery(); 
    Double GetSignal(); 
    Int32 GetIntegrationTime(); 
    Double GetDictionaryValue(String key); 
} 

interface IAnalogOutputter 
{ 
    double getVoltage(IOutputValueProvider provider); 
} 

class BatteryAnalogOutputter : IAnalogOutputter 
{ 
    double getVoltage(IOutputValueProvider provider) 
    { 
     return provider.GetBattery(); 
    } 
} 

class DictionaryValueOutputter : IAnalogOutputter 
{ 
    public String DictionaryKey { get; set; } 
    public double getVoltage(IOutputValueProvider provider) 
    { 
     return provider.GetDictionaryValue(DictionaryKey); 
    } 
} 

那麼,我只需要確保Acquisition實現該接口:

class Acquisition : IOutputValueProvider 
{ 
    public Int32 IntegrationTime { get; set; } 
    public Double Battery { get; set; } 
    public Double Signal { get; set; } 
    public Dictionary<String, Double> DictionaryValues; 

    public double GetBattery() { return Battery;} 
    public double GetSignal() { return Signal; } 
    public int GetIntegrationTime() { return IntegrationTime; } 
    public double GetDictionaryValue(String key) 
    { 
     Double d = 0.0; 
     return DictionaryValues.TryGetValue(key, out d) ? d : 0.0; 
    } 
} 

這是不完美的,因爲現在有必須維持一個巨大的接口和一些重複的代碼Acquisition,但是我的應用程序的其他部分受到影響的風險要小得多。它還允許我開始繼承Acquisition而不必更改這些外部件。我希望這會在類似的情況下幫助其他人。

2

Strategy Pattern封裝了一個 - 通常是複雜的操作/計算。

要返回的電壓取決於

  • 件配置
  • 採集數據的一些

所以我把這些到另一個類,並把它傳遞給戰略實施者。

另外在序列化方面,您沒有序列化策略類,也許只有它們的名稱或類型名稱。


UPDATE

嗯,看來你實現只需要一塊採集數據。這對於一種戰略模式來說有點不尋常 - 但我不認爲它更適合Visitor,所以策略是好的。除了實現者需要的配置之外,我還將創建一個具有屬性,採集數據(可能從中繼承)的類。

+0

澄清 - 採集數據包含約20條信息,所有這些信息將被各種電壓輸出器使用。每個實現只使用一個數據段,但是電壓輸出器的不同可能實現方式會有相同數量(20個)。那麼,我如何從'Acquisition'獲取到'另一個類將它傳遞給策略實現者?'?不過,關於序列化的好處,我肯定會考慮。 – drharris 2011-05-04 22:33:00

0

你可以做的一件事就是使用工廠方法來構建你的策略。您的個人策略可以將其構造函數僅存入其所需的單個數據元素,而工廠方法是唯一需要知道如何填充該數據的對象。事情是這樣的:

public class OutputterFactory 
{ 
    public static IAnalogOutputter CreateBatteryAnalogOutputter(Acquisition acq) 
    { 
     return new BatteryANalogOutputter(acq.Battery); 
    } 



} 
+0

我曾經想過,但是對於每一個新的數據來說,我必須添加一個屬性,一個方法和一個類。雖然它將它分離得更多一些,但它使得殘餘量增加了3倍。但是,我現在想知道是否爲此使用單獨的方法將是最佳選擇。 – drharris 2011-05-04 23:04:26