Avoiding coupling with Strategy pattern

孤者浪人 提交于 2019-12-05 09:03:45

Strategy Pattern encapsulates a - usually complex - operation/calculation.

The voltage you want to return is dependent on

  • pieces of configuration
  • Some of the acquisition data

So I would put these into another class and pass it to strategy implementors.

Also in terms of serialisation, you do not have serialise the strategy classes, perhaps only their name or type name.


UPDATE

Well, it seems that your implementations need only one piece of the acquisition data. That is a bit unusual for a strategy pattern - but I do not believe it fits Visitor better so strategy is fine. I would create a class which has as property, acquisition data (perhaps inherits from it) in addition to configuration that implementors need.

One thing you could do is use factory methods to construct your Strategies. Your individual strategies can take in their constructor only the individual data elements they need, and the factory method is the only thing that needs to know how to fill in that data given an Acquisition object. Something like this:

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



}

Ok, I hate to not give someone else the credit here, but I found a hybrid solution that works very well for my purposes. It serializes perfectly, and greatly simplifies the addition of new output types. The key was a single interface, IOutputValueProvider. Also note how easily this pattern handles the retrieval of varying ways of storing the data (such as a Dictionary instead of a parameter).

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);
    }
}

So then, I just need to ensure Acquisition implements the interface:

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;
    }
}

This isn't perfect, since now there's a gigantic interface that must be maintained and some duplicate code in Acquisition, but there's a heck of a lot less risk of something being changed affecting the other parts of my application. It also allows me to start subclassing Acquisition without having to change some of these external pieces. I hope this will help some others in similar situations.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!