Что такое «тонкая грань» между тонкими и толстыми интерфейсами? - PullRequest
4 голосов
/ 22 октября 2011

У меня есть система бронирования, которая позволяет вам забронировать бронирование, изменить существующее бронирование и отменить существующее бронирование. Я изучал принцип разделения интерфейсов, и мне было интересно, насколько тонкими должны быть мои интерфейсы и нарушаю ли я принцип единой ответственности. Мой первоначальный дизайн был:

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). Как вы определяете, что должно входить в интерфейс, а что должно быть разделено на другой интерфейс, класс и т. Д ...

Ответы [ 3 ]

5 голосов
/ 22 октября 2011

У вас есть две вещи, которые вы должны учитывать при рассмотрении области действия ваших интерфейсов:

  1. Имеет ли смысл требовать от каждого IReservation реализации этих членов?
  2. Имеет ли смысл ссылаться на участника X без участника Y?

Первое, о чем вы рассказали, и пришли к выводу «Нет».Второе, однако, не менее важно.Имеет ли смысл думать о чем-то, что можно «изменить», не имея возможности делать что-то еще?Если нет, подумайте о том, чтобы сделать IReservation и IModifiableReservation или какую-то другую группу функций.

Например, кажется, что Cancel и Modify идут рука об руку, поэтому, возможно, захотитепоместите их вместе в IModifiableReservation, затем попросите ваш класс реализовать этот интерфейс.

Когда он у вас есть, это кажется слишком гранулированным.

1 голос
/ 11 мая 2013

Я бы предложил иметь два интерфейса

interface IBookableReservation
{
     void Book();
}

и , как предложено от Адам Робинсон

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

Вы не делаетенеобходимо создать интерфейс IReservation, но наследовать ваш класс напрямую от IBookableReservation и IModifiableReservation.Клиенты могут использовать один или оба интерфейса.

Нет смысла создавать интерфейс, который просто дублирует общедоступные методы одного класса.Если интерфейс имеет то же имя, что и класс, только с префиксом «I», это запах кода, поскольку он указывает на то, что между интерфейсом и конкретными классами, реализующими it, есть отношение 1: 1.1015 *

См.

Принцип повторного использования абстракций (RAP)

и от http://martinfowler.com/bliki/InterfaceImplementationPair.html

Использование интерфейсов, когда вы не собираетесь использовать несколько реализацийЭто дополнительные усилия, чтобы держать все в курсе. Более того, он скрывает случаи, когда вы действительно предоставляете несколько реализаций.

0 голосов
/ 22 октября 2011

Если вашему приложению действительно нужно поддерживать различные виды резервирований, и позже некоторая общая логика должна быть способна обрабатывать все из них - я бы предложил ввести отдельный интерфейс для каждого типа сервиса и один интерфейс для самого резервирования, идея - резервирование предоставляет наборсервисов, так что вы можете просто предоставить список сервисов, абстрагированных от общего интерфейса IReservationService, и избавиться от реализации нескольких интерфейсов для каждой системы бронирования.Просто создайте один класс для каждой услуги и зарегистрируйте услуги через ctor of 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;
       }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...