6

私たちは、さまざまな種類の料金を顧客に請求するために使用するシステムを持っています。

複数の課金タイプがあり、各課金タイプには異なる課金アイテムが含まれます。

以下は、Factory Method を使用して思いついたものです。これの問題は、電荷の種類に応じて、各 Calculate 関数に異なるパラメーターを渡す必要があることです。どうすればこれを達成できますか?

    //product abstract class
    public abstract class ChargeItem
    {
        public abstract List<ChargeResults> Calculate();
    }

    //Concrete product classes
    public class ChargeType1 : ChargeItem
    {
        public override List<ChargeResults> Calculate()
        {
            return new List<ChargeResults> { new ChargeResults { CustomerId = 1, ChargeTotal = 10} };
        }
    }

    public class ChargeType2 : ChargeItem
    {
        public override List<ChargeResults> Calculate()
        {
            return new List<ChargeResults> { new ChargeResults { CustomerId = 2, ChargeTotal = 20} };
        }
    }

    public class ChargeType3 : ChargeItem
    {
        public override List<ChargeResults> Calculate()
        {
            return new List<ChargeResults> { new ChargeResults { CustomerId = 3, ChargeTotal = 30} };
        }
    }

    //Creator abstract class
    public abstract class GeneralCustomerCharge
    {
        //default constructor invokes the factory class
        protected GeneralCustomerCharge()
        {
            this.CreateCharges();
        }

        public List<ChargeItem> ChargeItems { get; protected set; }

        public abstract void CreateCharges();
    }

    public class AssetCharges : GeneralCustomerCharge
    {
        public override void CreateCharges()
        {
            ChargeItems = new List<ChargeItem> { new ChargeType1(), new ChargeType2() };
        }
    }

    public class SubscriptionCharges : GeneralCustomerCharge
    {
        public override void CreateCharges()
        {
            ChargeItems = new List<ChargeItem> { new ChargeType3() };
        }
    }

    public class ChargeResults
    {
        public int CustomerId { get; set; }
        public decimal ChargeTotal { get; set; }
    }

そして使用法は次のとおりです。

        var newAssetCharge = new AssetCharges();

        foreach (ChargeItem chargeItem in newAssetCharge.ChargeItems)
        {
            foreach (var item in chargeItem.Calculate())
            {
                Console.WriteLine("Asset Charges For Customer Id: {0}, Charge Total:     {1}", item.CustomerId, item.ChargeTotal);
            }               
        }

呼び出している Calculate メソッドに応じて、foreach ループ内から chargeItem.Calculate() にさまざまなタイプのパラメータを渡すことができるようにする必要があります。どうすればこれを達成できますか?

料金の種類ごとに異なる料金の種類のパラメーター クラスを作成し、料金の種類を決定し、if else ステートメントを使用して、関連するパラメーターの種類を渡す Calculate 関数を呼び出すことを計画していましたが、それは良い考えではないと思います。これを行うためのより良い方法はありますか、それとも私がここでやろうとしていることを達成する別の完全に異なる方法はありますか?

ありがとう

4

2 に答える 2

3

場合によります。これを達成する方法はたくさんありますが、どれを選択するかは、ここで簡単に共有できるよりも多くのコンテキストに依存します。ここにいくつかのアイデアがあります:

  • さまざまな引数をすべて保持する型を作成し、CalculateParamsそれらを主要な場所でのみ使用します。
  • この情報をChargeItemat 構造に配置します。
  • これらの両方の情報を担当する ChargeCalculator を作成します
  • 等...

この問題が発生している理由は、「中間」から設計しようとしているからです。必要な抽象化を取得する良い方法は、それらの抽象化に依存するクラスのコードとテストを作成することです。それらの抽象化がどのように見えるべきかを推測するのではなく、作成しているテストと本番コードのニーズに基づいたメソッドをその場で発明してください。これは、その名前が示すように、ニーズを最もよく満たす傾向があるニーズベースの抽象化を作成できるようにするための最良の方法です。

于 2013-01-29T13:20:04.920 に答える
1

上記の@Ryan Bennettからのコメントを拡張すると、これができると思います。

  1. Calculatorメソッドでインターフェイスを作成しますPerformCalculation()
  2. 適切な実装を返すメソッドをCalculatorFactory持つクラスを作成します。ファクトリは、メソッドに渡された引数 (if/else ステートメント)に基づいて実装オブジェクトを構築します。GenerateCalculator()CalculatorCalculatorGenerateCalculator()
  3. Calculator生成された実装を抽象Calculate()メソッドに渡します。

上記のコメントで述べたようにCalculatorCalculate()メソッドが依存する を注入します。抽象Calculate()メソッド (のChargeItem) の実装は、インターフェイスのみを考慮しCalculatorます。

を個別に実装Calculatorすると、ルールに基づいて計算が異なる方法で行われるようになります。

お役に立てれば。

于 2013-01-29T12:46:50.197 に答える