C# 避免与战略模式耦合

C# 避免与战略模式耦合,c#,oop,design-patterns,strategy-pattern,decoupling,C#,Oop,Design Patterns,Strategy Pattern,Decoupling,我试图将策略模式应用于特定情况,但遇到了一个问题,即如何避免将每个具体策略耦合到为其提供数据的上下文对象。下面是一个模式的简化示例,该模式以几种不同的方式出现,但应以类似的方式处理 我们有一个对象采集,它提供与特定时间帧相关的数据-基本上是使用不同硬件采集的一组外部数据。它已经太大了,因为它包含大量的数据,所以我不想给它任何进一步的责任。我们现在需要获取一些数据,并根据一些配置向硬件发送相应的电压 因此,想象一下以下(非常简化的)类: 现在,每个具体的strategy类都必须与我的Acquisi

我试图将策略模式应用于特定情况,但遇到了一个问题,即如何避免将每个具体策略耦合到为其提供数据的上下文对象。下面是一个模式的简化示例,该模式以几种不同的方式出现,但应以类似的方式处理

我们有一个对象
采集
,它提供与特定时间帧相关的数据-基本上是使用不同硬件采集的一组外部数据。它已经太大了,因为它包含大量的数据,所以我不想给它任何进一步的责任。我们现在需要获取一些数据,并根据一些配置向硬件发送相应的电压

因此,想象一下以下(非常简化的)类:

现在,每个具体的strategy类都必须与我的Acquisition类耦合,Acquisition类也是最有可能被修改的类之一,因为它是我们应用程序的核心。这仍然是对旧设计的改进,旧设计在
Acquisition
类中是一个巨大的switch语句。每种类型的数据可能有不同的转换方法(电池是一种简单的传递方式,其他的则没有那么简单),所以我觉得策略模式或类似的方法应该是可行的

我还将注意到,在最后的实现中,
ianalogoutput
将是一个抽象类,而不是一个接口。这些类将位于用户可配置的列表中,并序列化为XML文件。该列表必须在运行时可编辑并被记住,因此序列化必须是我们最终解决方案的一部分。以防有什么不同


我如何确保每个实现类都能获得工作所需的数据,而不将其绑定到我最重要的类之一?还是我以完全错误的方式处理这类问题?

策略模式
封装了一个通常很复杂的操作/计算

要返回的电压取决于

  • 配置块
  • 一些采集数据
因此,我将把它们放到另一个类中,并将其传递给策略实施者

同样在序列化方面,您没有序列化策略类,可能只有它们的名称或类型名称


更新
好吧,看起来您的实现只需要一段采集数据。这对于策略模式来说有点不寻常,但我不认为它更适合
Visitor
,所以策略是好的。我将创建一个类,除了实现者需要的配置之外,该类还具有作为属性的采集数据(可能从中继承)

你可以做的一件事是使用工厂方法来构建你的战略。您的单个策略只能在其构造函数中包含它们所需的单个数据元素,而工厂方法是唯一需要知道如何在给定
采集
对象的情况下填充该数据的方法。大概是这样的:

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



}

好吧,我不想在这里不给别人荣誉,但我发现了一个混合解决方案,非常适合我的目的。它可以完美地序列化,并大大简化了新输出类型的添加。密钥是一个单一接口,
IOutputValueProvider
。还请注意,此模式处理各种数据存储方式(例如字典而不是参数)的检索是多么容易

因此,我只需要确保
采集
实现接口:

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;
    }
}
类获取:IOutputValueProvider
{
公共Int32集成时间{get;set;}
公用双电池{get;set;}
公共双信号{get;set;}
公共词典价值;
公用双GetBattery(){返回电池;}
公共双GetSignal(){return Signal;}
public int GetIntegrationTime(){return IntegrationTime;}
公共双GetDictionaryValue(字符串键)
{
双d=0.0;
返回字典值。TryGetValue(键,输出d)?d:0.0;
}
}

这并不完美,因为现在有一个庞大的界面必须维护,在
采集
中有一些重复的代码,但是更改某些内容影响应用程序其他部分的风险要小得多。它还允许我开始子类化
Acquisition
,而无需更改这些外部部分。我希望这将有助于类似情况下的其他人。

澄清一下-采集数据包含大约20条信息,所有这些信息将由各种电压输出装置使用。每个实现将只使用一段数据,但电压输出器的不同可能实现的数量相同(20)。那么,我如何从
获取
到“另一个类[将其]传递给战略实施者”?虽然序列化很好,但我会考虑的。我已经考虑过了,但是对于每一个新的数据,我必须添加一个属性、一个方法和一个类。虽然它确实将其解耦了一点,但它使原油量增加了3倍。但是,我现在想知道,仅仅使用单独的方法是否是最好的选择。
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);
    }
}
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;
    }
}