【已更新最新开发文章,点击查看详细】
最常见的方案是安全地将成员添加到已经由无数客户端发布并使用的接口。
在本教程中,你将了解:
- 通过使用实现添加方法,安全地扩展接口。
- 创建参数化实现以提供更大的灵活性。
- 使实现器能够以替代的形式提供更具体的实现。
01 系统必备
从 .NET Core 3.0 预览版 4 开始提供默认接口成员。
02 方案概述
以下是客户的接口定义:
public interface ICustomer { IEnumerable<IOrder> PreviousOrders { get; } DateTime DateJoined { get; } DateTime? LastOrder { get; } string Name { get; } IDictionary<DateTime, string> Reminders { get; } }
他们定义了表示订单的第二个接口:
public interface IOrder { DateTime Purchased { get; } decimal Cost { get; } }
他们的目标是与现有客户建立更深入的关系,并改善他们与新客户的关系。
ICustomer 的每个实现都可以为忠实客户折扣设置不同的规则。
库作者可以向接口添加新成员,并为这些成员提供默认实现。
如果他们的业务规则不同,则可以进行替代。
03 使用默认接口成员升级
团队就最有可能的默认实现达成一致:针对客户的忠实客户折扣。
所有现有的和任何新的实现都可以使用默认实现,或者提供其自己的实现。
首先,将新方法添加到实现中:
// Version 1: public decimal ComputeLoyaltyDiscount() { DateTime TwoYearsAgo = DateTime.Now.AddYears(-2); if ((DateJoined < TwoYearsAgo) && (PreviousOrders.Count() > 10)) { return 0.10m; } return 0; }
库作者编写了用于检查实现的第一个测试:
SampleCustomer c = new SampleCustomer("customer one", new DateTime(2010, 5, 31)) { Reminders = { { new DateTime(2010, 08, 12), "childs's birthday" }, { new DateTime(1012, 11, 15), "anniversary" } } };
SampleOrder o = new SampleOrder(new DateTime(2012, 6, 1), 5m); c.AddOrder(o); o = new SampleOrder(new DateTime(2103, 7, 4), 25m); c.AddOrder(o); // 检查折扣 ICustomer theCustomer = c; Console.WriteLine($"Current discount: {theCustomer.ComputeLoyaltyDiscount()}");
注意测试的以下部分:
// 检查折扣 ICustomer theCustomer = c; Console.WriteLine($"Current discount: {theCustomer.ComputeLoyaltyDiscount()}");
若要调用在接口中声明和实现的任何方法,该变量的类型必须是接口的类型,在本示例中为 ICustomer。
04 提供参数化
让我们添加一个静态方法,该方法可设置控制默认实现的三个参数:
// Version 2: public static void SetLoyaltyThresholds(TimeSpan ago, int minimumOrders = 10, decimal percentageDiscount = 0.10m) { length = ago; orderCount = minimumOrders; discountPercent = percentageDiscount; }
private static TimeSpan length = new TimeSpan(365 * 2, 0,0,0); // 2年 private static int orderCount = 10; private static decimal discountPercent = 0.10m; public decimal ComputeLoyaltyDiscount() { DateTime start = DateTime.Now - length; if ((DateJoined < start) && (PreviousOrders.Count() > orderCount)) { return discountPercent; } return 0; }
接口成员允许使用任何修饰符。
例如,以下代码设置“客户答谢”,奖励任何成为会员超过一个月的客户:
ICustomer.SetLoyaltyThresholds(new TimeSpan(30, 0, 0, 0), 1, 0.25m); Console.WriteLine($"Current discount: {theCustomer.ComputeLoyaltyDiscount()}");
05 扩展默认实现
对于最后一个功能,让我们稍微重构一下代码,以实现用户可能需要基于默认实现进行生成的方案。
接口成员的默认实现也调用此共享方法:
public decimal ComputeLoyaltyDiscount() => DefaultLoyaltyDiscount(this); protected static decimal DefaultLoyaltyDiscount(ICustomer c) { DateTime start = DateTime.Now - length; if ((c.DateJoined < start) && (c.PreviousOrders.Count() > orderCount)) { return discountPercent; } return 0; }
在实现此接口的类的实现中,替代可以调用静态帮助程序方法,并扩展该逻辑以提供“新客户”折扣:
public decimal ComputeLoyaltyDiscount() { if (PreviousOrders.Any() == false) return 0.50m; else return ICustomer.DefaultLoyaltyDiscount(this); }
GitHub 上的示例存储库中获取入门应用程序)。
这样一来,在发现针对同一功能概念的新要求时,可以更轻松地升级这些接口定义。
【已更新最新开发文章,点击查看详细】