示例 - 计算订单商品折扣的规则:
public class OrderItem
{
public int ItemId { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
public decimal Total => Quantity * Price;
}
折扣的合约(又名接口)可以这样定义:
public interface IDiscountRule
{
decimal CalculateDiscount(OrderItem item);
}
现在让我们实现一些折扣规则
- 基本折扣 (2%)
- 白银折扣 (5%)
- 黄金折扣 (10%)
类定义:
/// <summary>
/// Abstract base class for the discount rules
/// </summary>
public abstract class DiscountRule : IDiscountRule
{
private readonly int _percent;
protected DiscountRule(int percent)
{
_percent = percent;
}
/// <inheritdoc />
public decimal CalculateDiscount(OrderItem item)
{
if (item == null)
{
throw new ArgumentNullException(nameof(item));
}
decimal discount = item.Total * (decimal) (_percent/100.0);
return discount;
}
}
/// <summary>
/// 2% discount
/// </summary>
public class BasicDiscountRule : DiscountRule
{
public BasicDiscountRule() : base(2)
{
}
}
/// <summary>
/// 5% discount
/// </summary>
public class SilverDiscountRule : DiscountRule
{
public SilverDiscountRule() : base(5)
{
}
}
/// <summary>
/// 10% discount
/// </summary>
public class GoldDiscountRule : DiscountRule
{
public GoldDiscountRule() : base(10)
{
}
}
使用规则计算订单商品的折扣:
var item = new OrderItem
{
ItemId = 1,
Price = 50,
Quantity = 2
};
var rule = new SilverDiscountRule();
decimal discount = rule.CalculateDiscount(item);
现在让我们创建一个复合规则,以便将多个规则(折扣)应用于一个订单项:
/// <summary>
/// To apply multiple discount rules to an order item
/// </summary>
public class CompositeDiscountRule : IDiscountRule
{
private readonly List<Type> _discountTypes;
public CompositeDiscountRule()
{
_discountTypes = new List<Type>();
}
public CompositeDiscountRule(List<Type> discountTypes)
{
if (discountTypes == null)
{
throw new ArgumentNullException(nameof(discountTypes));
}
_discountTypes = discountTypes;
}
public void Register<T>() where T : IDiscountRule, new()
{
_discountTypes.Add(typeof(T));
}
/// <inheritdoc />
public decimal CalculateDiscount(OrderItem item)
{
decimal totalDiscount = 0;
foreach (var discountType in _discountTypes)
{
IDiscountRule rule = Activator.CreateInstance(discountType) as IDiscountRule;
if (rule != null)
{
totalDiscount += rule.CalculateDiscount(item);
}
}
return totalDiscount;
}
}
您可以将复合规则与类型列表一起使用:
var item = new OrderItem
{
ItemId = 1,
Price = 50,
Quantity = 2
};
// composite rule with types
var compositeRule = new CompositeDiscountRule(new List<Type>
{
typeof(GoldDiscountRule),
typeof(BasicDiscountRule)
});
decimal discount = compositeRule.CalculateDiscount(item); // discount = 12.0
或者,作为替代方案,使用泛型:
var item = new OrderItem
{
ItemId = 1,
Price = 50,
Quantity = 2
};
// composite rule using generics
compositeRule = new CompositeDiscountRule();
compositeRule.Register<BasicDiscountRule>();
compositeRule.Register<SilverDiscountRule>();
decimal discount = compositeRule.CalculateDiscount(item); // discount = 7.0