9

次のシナリオでは、販売価格を計算するためのさまざまな種類の販売アルゴリズムがあります。FixedSaleStrategyはbasePriceパラメーターを必要としませんが、他のすべての戦略実装はそれを必要とします。この冗長なパラメータを回避する良い方法はありますか?

public abstract class SalesStrategy
{
    public abstract double GetPrice(double basePrice, double saleAmount);
}
public class AmountOffSale : SalesStrategy
{
    public override double GetPrice(double basePrice, double salesAmount)
    {
        return basePrice - salesAmount;
    }
}
public class FixedPriceSale : SalesStrategy
{
    public override double GetPrice(double basePrice, double salesAmount)
    {
        return salesAmount;
    }
}
4

6 に答える 6

6

戦略パターンの中核にあるのは、呼び出し元のコードは呼び出されている実装を認識していないという考えです。

実装ごとに使用されるパラメーターを変更すると、このパターンのメリットを十分に享受できないことがわかります。呼び出し元は、使用される実装とその呼び出し方法を知る必要があります。

私がよく行うのは、情報のスーパーセット (PricingInfo のようなもの) を含むクラスを渡すことです。このクラスは常に同じ方法で入力され (理想的にはコードに集中化されます)、唯一の違いは戦略の実装です。

利点の 1 つは、以前は関係のなかった PricingInfo クラスにプロパティ (たとえば、systemDiscount など) を追加できることであり、システム全体への影響はそれほど大きくありません。

于 2010-07-31T01:21:08.757 に答える
5

いいえ。これは冗長なパラメーターではありません。SalesStrategy を使用するコードは、使用している具象クラスを認識してはならないため、メソッド シグネチャはすべての派生クラスで同一である必要があります。

于 2010-07-30T23:43:00.367 に答える
2

C# 4.0 を使用している場合は、次のようにパラメーターを逆にしてオプションにすることができます。basePrice

public abstract class SalesStrategy
{
    public abstract double GetPrice(double saleAmount, double basePrice = 0d);
}

public class AmountOffSale : SalesStrategy
{
    public override double GetPrice(double salesAmount, double basePrice)
    {
        return basePrice - salesAmount;
    }
}

public class FixedPriceSale : SalesStrategy
{
    public override double GetPrice(double salesAmount, double basePrice = 0d)
    {
        return salesAmount;
    }
}

次のことができることを意味します...

FixedPriceSale fixedPrice = new FixedPriceSale();
...
fixedPrice.GetPrice(salesAmount);

AmountOffSalebasePriceパラメーターはオプションではないことに注意してください。つまり、次のコードはコンパイルされません。

AmountOffSale amountOffSale = new AmountOffSale();
...
// No overload for method 'GetPrice' takes 1 arguments
amountOffSale.GetPrice(salesAmount); 
于 2010-07-30T23:42:55.907 に答える
0

私の意見では、良いものではありません。そのままにしておきます。params(単一のparams double [] priceDataを持つ)やのように使用できるさまざまなトリックがありますIDynamicObject。しかし、最もクリーンなのは、いくつかの戦略で余分なパラメーターを無視することです。

于 2010-07-30T23:39:57.830 に答える
0

インターフェースから無関係なパラメーターを削除する良い方法は、それらのパラメーターをサブクラスのコンストラクターで渡すことです。したがって、設計の代替案は次のようになります。

public interface SalesStrategy
    {
        double CalculatePrice(double basePrice);
    }

public class FixedPriceSale : SalesStrategy
    {
        public double CalculatePrice(double basePrice)
        {
            return basePrice;
        }
    }

public class AmountOffSale : SalesStrategy
    {
        public double SalesAmount { get; set; }

        public AmountOffSale(double salesAmount)
        {
            this.SalesAmount = salesAmount;
        }

        public double CalculatePrice(double basePrice)
        {
            return basePrice - SalesAmount;
        }
    }

その構成では、サブクラスからの特定のデータでインターフェイスを汚染しません。

于 2010-07-31T01:06:30.003 に答える
0

もう 1 つの方法は、パラメーター オブジェクトまたは を使用することDictionary<string, object>です。このようにして、各メソッドのパラメーターの数を統合し、将来要件が変更された場合に備えて追加のパラメーターの余地を残すことができます。

1 つの欠点はDictionary<string, object>、コードでパラメーターを追跡するのが難しくなる可能性があることです。一方、パラメーター オブジェクトには、コードで表示できるすべてのプロパティが含まれているだけです。

于 2010-07-31T01:16:15.600 に答える