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

ここで、すべての具体的な戦略クラスを私の取得クラスに結合する必要があります。これは、アプリケーションの中核であるため、変更される可能性が最も高いクラスの1つでもあります。これは、クラス内の巨大なswitchステートメントであった古い設計をまだ改善したものです。Acquisitionデータの種類ごとに変換方法が異なる場合があります(Batteryは単純なパススルーですが、他のデータはそれほど単純ではありません)。そのため、戦略パターンなどを使用する必要があると思います。

IAnalogOutputterまた、最終的な実装では、インターフェイスではなく抽象クラスになることにも注意してください。これらのクラスは、ユーザーが構成可能でXMLファイルにシリアル化されるリストに含まれます。リストは実行時に編集可能で記憶されている必要があるため、Serializableは最終的なソリューションの一部である必要があります。それが違いを生む場合に備えて。

最も重要なクラスの1つに結び付けずに、各実装クラスが機能するために必要なデータを確実に取得するにはどうすればよいですか?それとも、私はこの種の問題に完全に間違った方法で取り組んでいますか?

4

3 に答える 3

2

Strategy Pattern-通常は複雑な-操作/計算をカプセル化します。

戻したい電圧は

  • 構成の一部
  • 取得データの一部

したがって、これらを別のクラスに入れて、戦略の実装者に渡します。

また、シリアル化に関しては、ストラテジークラスをシリアル化する必要はなく、おそらく名前またはタイプ名のみをシリアル化する必要があります。


アップデート

さて、あなたの実装は取得データの1つの部分だけを必要とするようです。これは戦略パターンとしては少し珍しいことですが、それがより適切であるとは思わないVisitorので、戦略は問題ありません。実装者が必要とする構成に加えて、取得データ(おそらくそれを継承する)をプロパティとして持つクラスを作成します。

于 2011-05-04T22:27:39.090 に答える
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また、これらの外部部品の一部を変更することなく、サブクラス化を開始することもできます。これが、同様の状況にある他の人に役立つことを願っています。

于 2011-05-17T04:45:18.663 に答える
0

できることの 1 つは、ファクトリ メソッドを使用して戦略を構築することです。個々の戦略は、必要な個々のデータ要素のみをコンストラクターで受け取ることができます。ファクトリ メソッドは、Acquisitionオブジェクトを指定してそのデータを埋める方法を知る必要がある唯一のものです。このようなもの:

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



}
于 2011-05-04T22:49:18.757 に答える