Если вы всегда используете код для интерфейсов на Java

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

Должен ли я кодировать интерфейсы для каждого класса, который я пишу, или это overkill? Я не хочу удвоить количество исходных файлов в проекте, если это действительно того стоит.

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

Ответ 1

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

Но не всегда легко заранее знать, что может измениться в будущем, особенно если вы не так опытны. Я думаю, что решение этой проблемы - рефакторинг: простота (без интерфейса), если она не нужна. Когда возникает необходимость, просто выполните рефакторинг "Ввести/Извлечь интерфейс" (поддерживается практически всеми достойными IDE).

Когда вы делаете это, извлекайте только те методы, которые действительно нужны вызывающим. Не бойтесь извлекать больше отдельных интерфейсов (если не все извлеченные методы действительно согласованы).

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

Изменить: на основе комментария Тарски. Я понял еще один важный сценарий/корректировку предыдущих утверждений:
Если вы предоставляете внешний API (для других [sub] проектов или действительно выпускаете его "в диком" ), то использование интерфейсов в API (за исключением простых классов значений) почти всегда является хорошей идеей.
Это позволит вам изменить имплантат, если хотите, не нарушая код клиента. У вас будет проблема только в том случае, если вам также придется изменить интерфейс. Не нарушать совместимость будет очень сложно (если не невозможно).

Ответ 2

Я использую его, когда по крайней мере одно из следующего верно:

1) Я хочу отделить несвязанные модули/классы друг от друга, и я хочу, чтобы он отражался в зависимости от java-пакета.

2) Когда развязка важна с точки зрения зависимостей построения

3) Когда реализация может изменяться через конфигурацию или динамически во время выполнения (обычно из-за какого-то шаблона проектирования)

4) Когда я хочу, чтобы класс проверялся, я делаю его "точки ссылки" на внешние интерфейсы ресурсов, чтобы я мог использовать макетные реализации.

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

Ответ 3

Нет, у каждого класса не должно быть интерфейса. Он переполняет квадрат.

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

Посмотрите на API java.util Collections для хорошего примера. Интерфейс List - это хорошая абстракция для общей идеи List, но вы можете видеть, что существует множество способов ее реализации: ArrayList, LinkedList и т.д.

UPDATE: как насчет того случая, когда вы создаете конкретный класс, решаете после того, как у вас есть клиенты, которым нужен интерфейс, а затем вы разбиваете своих клиентов, добавляя интерфейс? Да, что происходит. Откуда вы знаете, чего не знаете? Никакое программное обеспечение или методология не могут это исправить.

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

Я бы сказал, что слои, такие как службы и настойчивость, всегда должны иметь интерфейсы. Все, что может быть проксировано, должно иметь интерфейс. Если вы делаете Spring AOP, все, что вы хотите украсить с помощью аспект, должно иметь интерфейс.

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

Остальные попадают в серые области. Используйте свое лучшее мнение.

Ответ 4

Короче говоря, нет. Вы являетесь создателем приложения, поэтому у вас есть достойное представление о том, что может измениться. На мой взгляд, некоторые из книг по шаблонам дизайна немного сумасшедшие, поскольку они, кажется, всегда подталкивают дизайн к интерфейсам, а не реализацию, несмотря ни на что. Иногда это просто избыток. Для моего последнего приложения (малый размер) у меня есть интерфейс базы данных, потому что я думаю, что есть вероятность, что я смогу позже перенести его в Интернет и переключиться на MySQL. Конечно, на самом деле было бы легко создать интерфейс базы данных по дороге из моего существующего класса и просто добавить "реализует myDbInterface" позже с небольшими изменениями. Это работает, потому что я единственный разработчик. В более крупной команде или другом типе продукта это может быть другой ответ. Просто используйте свое лучшее суждение (после прочтения всех хороших ответов SO, конечно).

Ответ 5

Мне нравится думать, что один использует интерфейсы, когда важна вместимость и потенциал для разных действий. Услуги идеально подходят. Может потребоваться реализация по умолчанию, но подделка (mocking) и т.д. - другая. Это, очевидно, означает, что должен быть intf, так как всегда будет как минимум 2 формы.

С другой стороны, типы значений должны быть конечными классами. Они никогда не должны расширяться. Типы значений включают нечто вроде Suburb, MimeType. Если есть вариации этих композиций использования. В качестве цели я стараюсь прикладывать небольшое поведение, если оно есть в моих значениях. Подтверждение простого типа, который он обертывает и т.д., Вероятно, является самой сложной вещью, которую он делает. Например, класс "Цвет", который принимает значение r/g/b, должен проверить, что каждый компонент находится между 0 и 255 и т.д.

Ответ 6

Да, используйте интерфейс, если вы ожидаете изменения поведения., В будущем.

Или ваш класс, который может корректно обрабатывать изменения.

например.

public static void main(String s[])
{
 Employee e1=new Employee(new Salesman());
 Employee e2=new Employee(new Manager());

 system.out.println(e1.performaction());
 system.out.println(e1.performaction());
}

Class Employee
{

//which changes frequently
Authority a;

public Employee(Authority a)
{
this.a=a;
}    
public String performAction()
{
a.action();
}
}

//--------------------------------------------- ---------------------

interface Authority
{ 
public String action();
}

class Manager implements Authority 
{ 
public String action()
{
 returns "I manages People";
}

 class SalesMan implements Authority 
{
  public String action() 
{
 returns "I Sell things Company makes ";
}
}