薄接口和胖接口之间的"Thin line"是什么?



我有一个预订系统,它允许您预订、修改现有预订和取消现有预订。我正在研究接口隔离原则,我想知道我应该把我的接口做得多薄,如果我违反了单一职责原则。我最初的设计是:

interface IReservation
{
     void Book();
     void Modify();
     void Cancel(); 
}

,但后来我想,如果一个预订系统不需要为预订实现这些方法之一,而只与预订有关,那么我做了以下操作:

interface IBook
{
     void Book();
}

interface IModify
{
    void Modify();
}
interface ICancel
{
    void Cancel();
}

现在我可以这样做:

interface IReservation : IBooking
{

}

interface IReservation : IBooking, IModify
{

}

所以问题就变成了我是不是把它弄得太薄了。此外,为接口命名也变得更加困难,例如,我不喜欢IModify或ICancel(对我来说,它们就像是应该在IReservation接口上的方法)。如何决定什么应该进入一个接口,什么应该被隔离到另一个接口、类等……

在查看接口的作用域时必须考虑两件事:

  1. 要求每个IReservation实现这些成员有意义吗?
  2. 不引用成员Y而引用成员X有意义吗?

第一个是你已经涵盖的内容,并且得出了"不"的结论。第二点同样重要。认为某物"可以修改"而不能够做任何其他事情有意义吗?如果没有,请考虑使用IReservationIModifiableReservation,或者其他一些功能分组。

例如,CancelModify似乎是齐头并进的,所以可能想把它们都放在IModifiableReservation上,然后让你的类实现该接口。

看起来有点太细了

我建议有两个接口

interface IBookableReservation
{
     void Book();
}

和Adam Robinson的建议

interface IModifiableReservation
{
   void Modify();
   void Cancel();
}

你不需要创建IReservation接口,而是直接从ibookablerreservation和imodifiablelerreservation继承你的类。客户端可以使用一个接口,也可以同时使用两个接口。

没有必要创建一个接口,它只是复制一个类的公共方法。如果接口的名称与类的名称相同,只是前缀为"I",这是一种代码气味,因为它表明接口和实现它的具体类之间是1:1的关系。

参见重用抽象原则(RAP)

and from http://martinfowler.com/bliki/InterfaceImplementationPair.html

在不需要多个接口时使用接口实现是保持所有内容同步的额外工作。此外它隐藏了实际提供多个的情况实现。

如果您的应用程序确实需要支持不同类型的预订,并且以后一些公共逻辑应该能够处理所有预订—我建议为每个服务类型引入单独的接口,为每个预订本身引入单个接口,其思想—预订提供一组服务,因此您只需公开由公共接口IReservationService抽象的服务列表,并摆脱每个预订系统的多个接口实现。只需为每个服务创建一个类,并通过Reservation函数注册服务:

var reservationWithBooking = 
     new Reservation(new List<IReservationService { new BookingService() });
var reservationWithCancellation = 
     new Reservation(new List<IReservationService { new CancellationService(); });
var mixedReservation = 
     new Reservation(new List<IReservationService 
                            {
                                new BookingService(),
                                new CancellationService()
                            });

接口:

interface IReservationService
{       
}
interface IBookingService : IReservationService
{
   void Book(...);
}
interface ICancellationService : IReservationService
{
   void Cancel(...);
}
interface IReservation
{
   IEnumerable<IReservationService> Services { get; }
}
class Reservation : IReservation
{
    private IList<IReservationService> services;
    public Reservation(IEnumerable<IReservationService> services)
    {
       this.services = new List<IReservationService>(services);
    }
    public IEnumerable Services<IReservationService> 
    { 
       get 
       {
          return this.services;
       }
    }
}

最新更新