Бесполезные интерфейсы - PullRequest
22 голосов
/ 05 июня 2009

Зачем вам когда-либо использовать интерфейс, если у вас будет только одна его реализация?

Ответы [ 25 ]

2 голосов
/ 05 июня 2009

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


Интерфейсы с одним методом для передачи фрагментов логики реализации:

public interface IComparable<T>
{
    int CompareTo(T first, T second);
}

public static class Array<T>
{
    public void Sort(T[] input)
    {
        if (T is IComparable) { /* sorting implementation */ }
        else { Throw new Exception("Doesn't implement IComparable"); }
    }
}

Может быть заменено на:

public static class Array<T>
{
    public void Sort(T[] input, Func<T, T, int> compare)
    {
        /* sorting implementation */
    }
}

Я считаю функциональный стиль выше более читабельным и многократно используемым.


Интерфейсы с одним методом для ввода-вывода зависимостей:

public interface IFailureNotifier
{
    void HandleFailure(Exception ex);
}

public class TransactionProcessor
{
    public IFailureNotifier FailureNotifier { get; set; }

    public TransactionProcessor(IFailureNotifier failureNotifier)
    {
        this.FailureNotifier = failureNotifier;
    }

    public void ProcessItems(object[] items)
    {
        try
        {
            for(object item in items) { /* do stuff */ }
        }
        catch(Exception ex)
        {
            FailureNotifier.HandleFailure(ex);
        }
    }
}

Может быть переписано как:

public class TransactionProcessor
{
    public Action<Exception> FailureNotifier { get; set; }

    public TransactionProcessor(Action<Exception> failureNotifier)
    {
        this.FailureNotifier = failureNotifier;
    }

    public void ProcessItems(object[] items)
    {
        try
        {
            for(object item in items) { /* do stuff */ }
        }
        catch(Exception ex)
        {
            FailureNotifier(ex);
        }
    }
}

Преимущество этого подхода заключается в более простой библиотеке классов: мне не нужен набор мелких объектов для реализации одиночного метода IFailureNotifier, я просто вместо этого передаю реализацию напрямую.


Это не означает, что интерфейсы с одним методом плохие , вы все еще хотите заключить функцию в интерфейс, если функция зависит от основного изменяемого состояния. Однако я лично нахожу, что большинство преимуществ интерфейсов с одним методом уже обеспечены первоклассными функциями.

1 голос
/ 05 июня 2009

Когда я работаю с кем-то еще над проектом, например, если я выполняю интерфейс (например, веб-приложение), а другой человек выполняет всю работу с базой данных, мы начинаем с написания API. Сторона, которая стоит передо мной, связана с проблемной областью: классы для пользователя, администратора, сотрудника, SKU или чего-либо еще. Тогда мы можем работать самостоятельно; она реализует все интерфейсы, и я пишу код, который их использует.

1 голос
/ 06 июня 2009

Да, особенно с Delphi.

Если у вас есть ссылка интерфейса на объект, то вы получите счетчик ссылок автоматически. Так что на самом деле обычно иметь интерфейс только с одной реализацией, когда вы хотите, чтобы объект был очищен автоматически. Подсчет ссылок лучше сборщика мусора, поскольку деструктор объекта вызывается, как только последняя ссылка выходит из области видимости или перестает ссылаться на нее.

1 голос
/ 05 июня 2009

В некоторых случаях для наглядности: вы можете захотеть, чтобы определенные части кода видели конкретный класс и имели доступ к установщикам, а некоторые другие - только для получателей: предоставьте им доступ только к интерфейсу.

Этого не всегда можно достичь с помощью public / protected / private.

1 голос
/ 05 июня 2009

Если вы работаете с системой, которая допускает рефакторинг, вы должны добавлять интерфейсы только в том случае, если это необходимо для спецификации (скажем, внешнего API) или если вам нужно несколько реализаций. Я считаю тестовые объекты допустимыми интерпретациями, поэтому, если вам нужен интерфейс для того, чтобы его протестировать, то это хороший вариант использования интерфейсов.

Объекты значений редко должны становиться интерфейсами, а объекты служб часто становятся интерфейсами.

0 голосов
/ 05 июня 2009

Чтобы обеспечить слабую связь, лучше полагаться на абстрактную зависимость, чем привязывать себя к конкретному классу.

Одним из примеров, где эта практика особенно полезна, является подход удаленного взаимодействия *1004*, основанный на использовании прокси-сервера Spring.

0 голосов
/ 05 июня 2009

, поскольку интерфейс лучше всего подходит для точного указания типа

0 голосов
/ 05 июня 2009

Возможность расширения позже в будущем.

0 голосов
/ 05 июня 2009

Одна ситуация для интерфейса только для одной реализации: RMI. У вас есть объект в одном приложении, и вы будете использовать его из другого приложения через RMI; вам нужно иметь интерфейс. Таким образом, вам даже не нужно включать класс реализации в вызывающее приложение, что может спасти вызывающее приложение от включения множества J2EE-материалов или внешних библиотек, которые может использовать реализация.

Другая причина: сегодня у вас есть только одна реализация, но завтра в JDK или во внешней библиотеке может быть что-то, что может привести к изменению этой реализации (возможно, созданию новой). Ваша система может измениться, и вам нужно добавить новую реализацию, сохранив старую; некоторое обслуживание и т. д.

0 голосов
/ 05 июня 2009

Я часто делаю это по нескольким причинам:

1) Позволяет указать, какие функции класса фактически используются за пределами класса. Это говорит вам, какие функции вам всегда нужно поддерживать, пока этот интерфейс остается неизменным. Это позволяет вам использовать другие открытые методы в этом классе по любой причине (для поддержки других интерфейсов или для других объектов, которые имеют экземпляр объекта и ссылаются на него по фактическому имени класса, а не через интерфейс).

2) Также обрезает список, предоставленный через intellisense, только для функций, поддерживаемых интерфейсом.

3) И, как указано выше, это полезно для модульного тестирования и макетов фреймворков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...