Интерфейс определяет методы , на которые объект отвечает.
Когда вы кодируете интерфейс , вы можете изменить базовый объект, и ваш код будет все еще работать (поскольку ваш код не зависит от ВОЗ, выполняющей работу или КАК ее выполнять выполняется) Таким образом, вы получаете гибкость.
Когда вы кодируете конкретную реализацию , если вам нужно изменить базовый объект, ваш код , скорее всего, сломается , поскольку новый объект может не отвечать на те же методы.
Итак, приведу ясный пример:
Если вам нужно держать несколько объектов, вы, возможно, решили использовать Vector .
Если вам нужен доступ к первому объекту вектора, вы можете написать:
Vector items = new Vector();
// fill it
Object first = items.firstElement();
Пока все хорошо.
Позже вы решили, что по какой-то причине вам нужно изменить реализацию (скажем, вектор создает узкое место из-за чрезмерной синхронизации)
Вы понимаете, что вам нужно использовать ArrayList instad.
Ну, твой код сломается ...
ArrayList items = new ArrayList();
// fill it
Object first = items.firstElement(); // compile time error.
Ты не можешь. Эта строка и все те строки, которые используют метод firstElement () , прервутся.
Если вам нужно определенное поведение и вам определенно нужен этот метод, он может быть в порядке (хотя вы не сможете изменить реализацию) Но , если вам нужно просто получить первый элемент (то есть нет ничего особенного в Vector, кроме того, что он имеет метод firstElement ()), тогда использование интерфейса, а не реализации даст вам гибкость для изменения.
List items = new Vector();
// fill it
Object first = items.get( 0 ); //
В этой форме вы кодируете не метод get вектора , а метод get списка .
Неважно, как базовый объект выполняет метод, если он отвечает на контракт «получить 0-й элемент коллекции»
Таким образом, позже вы можете изменить его на любую другую реализацию:
List items = new ArrayList(); // Or LinkedList or any other who implements List
// fill it
Object first = items.get( 0 ); // Doesn't break
Этот пример может показаться наивным, но является основой, на которой основана технология ОО (даже для тех языков, которые не имеют статической типизации, таких как Python, Ruby, Smalltalk, Objective-C и т. Д.)
Более сложным примером является способ JDBC . Вы можете сменить драйвер, но большая часть вашего звонка будет работать так же. Например, вы можете использовать стандартный драйвер для баз данных Oracle или использовать более сложный драйвер, такой как Weblogic или Webpshere. Конечно, это не волшебство, вы все еще должны тестировать свой продукт раньше, но по крайней мере у вас нет таких вещей, как:
statement.executeOracle9iSomething();
против
statement.executeOracle11gSomething();
Нечто подобное происходит с Java Swing.
Дополнительное чтение:
Принципы проектирования из шаблонов проектирования
Эффективный элемент Java: ссылки на объекты по их интерфейсам
(Покупка этой книги - одна из лучших вещей, которую вы могли бы сделать в жизни - и прочитайте, если, конечно, -)