0

GiftCouponPayment クラスがあります。これには、頻繁に変更される可能性のあるビジネス戦略ロジック (GetCouponValue()) があります。現時点では、「クーポン番号が 2000 未満の場合、クーポンの値はゼロと見なされる」というロジックになっています。今後の事業戦略では、「クーポン発行日が2000年1月1日未満の場合、クーポン価値はゼロとみなすべき」と変更される可能性があります。会社の管理部門に基づいて、そのような戦略に変更できます。

GetCouponValue メソッドの戦略を変更するときにクラスを変更する必要がないように、戦略パターンを使用して GiftCouponPayment クラスをリファクタリングするにはどうすればよいでしょうか?

更新:責任を分析した後、「GiftCoupon」は「GiftCouponPayment」クラスのより良い名前になると感じています。

ここに画像の説明を入力

C# コード

    public int GetCouponValue()
    {
        int effectiveValue = -1;
        if (CouponNumber < 2000)
        {
            effectiveValue = 0;
        }
        else
        {
            effectiveValue = CouponValue;
        }

        return effectiveValue;
    }

読む

  1. 戦略パターン - 複数の戻り値の型/値
4

4 に答える 4

3

「クーポン値ポリシー」をクーポンオブジェクト自体に挿入し、それを呼び出してクーポン値を計算できます。このような場合、ポリシーに渡しthisて、ポリシーがクーポンに必要な属性(クーポン番号など)を要求できるようにすることができます。

public interface ICouponValuePolicy
{
  int ComputeCouponValue(GiftCouponPayment couponPayment);
}

public class GiftCouponPayment
{
  public ICouponValuePolicy CouponValuePolicy {
    get;
    set;
  }

  public int GetCouponValue()
  {
    return CouponValuePolicy.ComputeCouponValue(this);
  }
}

GiftCouponPaymentまた、あなたは2つのこと(支払いとギフトクーポン)に本当に責任があるようです。、、およびGiftCouponを含むクラスを抽出し、これを。から参照することは理にかなっているかもしれません。CouponNumberCouponValueGetCouponValue()GiftCouponPayment

于 2012-07-11T15:07:58.350 に答える
3

GiftCouponPayment クラスは GiftCoupon を異なる戦略クラスに渡す必要があります。したがって、戦略インターフェース ( CouponValueStrategy ) にはメソッドが含まれている必要があります。

int getCouponValue(GiftCoupon giftCoupon)

CouponValueStrategy を実装する各 Concrete 戦略はGiftCouponにアクセスできるため、それぞれがクーポン番号やクーポンの日付などに基づいてアルゴリズムを実装できます。

于 2012-07-11T15:02:37.147 に答える
2

ビジネスロジックが変更されると、コードも変更する必要があるのは当然です。

おそらく、有効期限検出ロジックを仕様クラスに移動することを選択できます。

    public class CouponIsExpiredBasedOnNumber : ICouponIsExpiredSpecification
    {

        public bool IsExpired( Coupon c )
        {
             if( c.CouponNumber < 2000 )
                 return true;
             else
                  return false;
        }
    }

    public class CouponIsExpiredBasedOnDate : ICouponIsExpiredSpecification
    {
       public readonly DateTime expirationDate = new DateTime (2000, 1, 1);

       public bool IsExpired( Coupon c )
        {
             if( c.Date < expirationDate )
                 return true;
             else
                  return false;
        }
    }

public class Coupon
{
     public int GetCouponValue()
     {
        ICouponIsExpiredSpecification expirationRule = GetExpirationRule();

        if( expirationRule.IsExpired(this) ) 
           return 0;
        else
           return this.Value;

     }
}

あなたが自分自身に尋ねるべき質問:今それをこれほど複雑にする必要がありますか?現在のニーズを満たすために可能な限り単純にし、後で有効期限ルールが実際に変更されたときにリファクタリングすることはできませんか?

于 2012-07-11T15:07:28.290 に答える
1

動的にしたい動作は、クーポンの計算です。これは、クーポンの日付、クーポン番号など、さまざまなものに依存する可能性があります。クーポンを計算するサービス クラスを挿入するには、プロバイダー パターンの方が適切だと思います。価値。

これの本質は、ビジネス ロジックを GiftCouponPayment クラスの外に移動し、"CouponCalculator" と呼ぶクラスを使用してビジネス ロジックをカプセル化することです。このクラスはインターフェースを使用します。

interface ICouponCalculator
{
    int Calculate (GiftCouponPayment payment);
}

public class CouponCalculator : ICouponCalculator
{
   public int Calculate (GiftCouponPayment payment)
   {
      if (payment.CouponNumber < 2000)
      {
         return 0;
      }
      else
      {
         return payment.CouponValue;
      }
   }
}

このインターフェイスとクラスができたので、GiftCouponPayment クラスにプロパティを追加し、元の GetCouponValue() メソッドを変更します。

public class GiftCouponPayment
{
   public int CouponNumber;
   public int CouponValue;

   public ICouponCalculator Calculator { get; set; }

   public int GetCouponValue()
   {
      return Calculator.Calculate(this);
   }
}

GiftCouponPayment クラスを作成するときに、Calculator プロパティを割り当てます。

var payment = new GiftCouponPayment() { Calculator = new CouponCalculator(); }
var val = payment.GetCouponValue(); // uses CouponCalculator class to get value

計算ロジックを GiftCouponPayment クラスの外に移動するだけでも大変な作業に思えるかもしれませんが、そうです。ただし、これが要件である場合は、いくつかのことが提供されます。

1. 計算ロジックを調整するために GiftCouponPayment クラスを変更する必要はありません。

2. ICalculator を実装する追加のクラスと、構築時に GiftCouponPayment に挿入するクラスを決定するファクトリ パターンを作成できます。これは、ロジックが非常に複雑になった場合に役立つため、「戦略」パターンに対する当初の要望をよりよく表しています。

于 2012-07-11T15:34:34.110 に答える