NHibernate系列之五_策略模式與繼承Table Per Class

  • 1509
  • 0

摘要:NHibernate系列之五_策略模式與繼承Table Per Class

最近看到一篇文章 http://lostechies.com/jimmybogard/2008/08/27/strategies-and-discriminators-in-nhibernate/,討論了如何應用Table Per Class來對應strategy模式的使用。我覺得以後可能用的到,就此記錄下來。

首先我有以下的類別結構。Order的SumAmount統計了所有OrderDetail的SellPrice與Quantity的乘積,依據使用不同 的付款方式,需支付不同的Fee。所以Order會向FeeStragety取得應支付的費用,然後存在FeeAmount裏面

Order類別內容如下,在ReCalculate時,向FeeStrategy取得額外支出的費用。

public class Order
{
   public virtual FeeStrategy Strategy { get; set; }
   ........

    public virtual void ReCalculate()
    {
        decimal total = 0;
        foreach (OrderDetail orderDetail in OrderDetails)
        {
            total += (orderDetail.SellPrice * orderDetail.Quantity);
        }

        SumAmount = total;

        this.FeeAmount = Strategy.GetFee(this);
    }
}

Order.hbm.xml的配置如下,使用多對一,關聯到FeeStrategy的ID


   .....
    
    

FeeStrategy類別是個父類別,並提供一個Creation的靜態Method,來產生子類別

public class FeeStrategy
{
   public virtual int No { get; set; }

   public virtual decimal GetFee(Order order)
   {
       return 0;
   }

   public static CreditCardFee newCreditCardFee()
   {
       CreditCardFee creditCardFee = new CreditCardFee();
       creditCardFee.No = 1;
       return creditCardFee;
   }
}

CreditCardFee子類別如下

public class CreditCardFee : FeeStrategy
{
    public virtual decimal FeePercent { get; set; }

    public override decimal GetFee(Order order)
    {
        return order.SumAmount * FeePercent;
    }
} 

FeeStrategy.hbm.xml的設定,把discriminator的欄位指定給No,所以Order可以透過關聯欄位FeeStategyNo,取得對應的子類別。


  
    
  

  
  
  
    
  

所以當我存入一筆Order

Order order = new Order();
 order.ShoppingDate = new DateTime(2012, 1, 14);

 ProductDesc productDesc = new ProductDesc();
 productDesc.Name = "鉛筆";
 productDesc.Price = 8;//實際價格

 OrderDetail orderDetail = new OrderDetail();
 orderDetail.Quantity = 20;
 orderDetail.SellPrice = 10;//售出時價格,所以總和是200
 orderDetail.SellProductDesc = productDesc;

 //使用信用卡支付,但要付總價1成的費用
 CreditCardFee creditCardFee = FeeStrategy.newCreditCardFee();
 creditCardFee.FeePercent = 0.1m;
 order.Strategy = creditCardFee;

 order.AddDetail(orderDetail);

預期到的結果如下

 Order order = session.Get(1);

 order.ReCalculate();

 Assert.IsInstanceOf(typeof(CreditCardFee), order.Strategy);
 Assert.AreEqual(20, order.FeeAmount);