Возможный дубликат:
Что означает "программировать интерфейс" ?
Я продолжаю понимать этот термин:
Программа для интерфейса.
Что именно это означает? Сценарий сценария реальной жизни будет высоко оценен.
Возможный дубликат:
Что означает "программировать интерфейс" ?
Я продолжаю понимать этот термин:
Программа для интерфейса.
Что именно это означает? Сценарий сценария реальной жизни будет высоко оценен.
Проще говоря, вместо того, чтобы писать свои классы таким образом, что
Я полагаюсь на этот конкретный класс, чтобы выполнять свою работу
вы пишете его таким образом, который говорит
Я полагаюсь на любой класс, который делает это, чтобы выполнять мою работу.
Первый пример представляет класс, который зависит от конкретной конкретной реализации для выполнения своей работы. По сути, это не очень гибко.
Второй пример представляет класс, написанный для интерфейса. Неважно, какой конкретный объект вы используете, он просто заботится о том, чтобы он осуществлял определенное поведение. Это делает класс более гибким, поскольку он может быть обеспечен любым количеством конкретных реализаций для выполнения своей работы.
В качестве примера конкретному классу может потребоваться выполнить некоторые протоколирования. Если вы пишете класс, зависящий от TextFileLogger, класс навсегда вынужден записывать свои записи журнала в текстовый файл. Если вы хотите изменить поведение ведения журнала, вы должны изменить сам класс. Класс тесно связан с его регистратором.
Если, однако, вы пишете класс, зависящий от интерфейса ILogger, а затем предоставляете класс TextFileLogger, вы выполнили бы то же самое, но с дополнительным преимуществом быть более гибким. Вы можете предоставить любой другой тип ILogger по своему усмотрению без изменения самого класса. Класс и его регистратор теперь слабо связаны, и ваш класс намного более гибкий.
Интерфейс представляет собой набор связанных методов, который содержит только сигнатуры этих методов, а не фактическую реализацию.
Если класс реализует интерфейс (class Car implements IDrivable
), он должен предоставить код для всех подписей, определенных в интерфейсе.
Основной пример:
У вас есть классы Car and Bike. Оба реализуют интерфейс IDrivable:
interface IDrivable
{
void accelerate();
void brake();
}
class Car implements IDrivable
{
void accelerate()
{ System.out.println("Vroom"); }
void brake()
{ System.out.println("Queeeeek");}
}
class Bike implements IDrivable
{
void accelerate()
{ System.out.println("Rattle, Rattle, ..."); }
void brake()
{ System.out.println("..."); }
}
Теперь предположим, что у вас есть коллекция объектов, которые все "управляемы" (их классы реализуют IDrivable):
List<IDrivable> vehicleList = new ArrayList<IDrivable>();
list.add(new Car());
list.add(new Car());
list.add(new Bike());
list.add(new Car());
list.add(new Bike());
list.add(new Bike());
Если вы теперь хотите перебрать эту коллекцию, вы можете положиться на то, что каждый объект в этой коллекции реализует accelerate()
:
for(IDrivable vehicle: vehicleList)
{
vehicle.accelerate(); //this could be a bike or a car, or anything that implements IDrivable
}
Вызывая этот метод интерфейса, вы не программируете реализацию, а интерфейс - это контракт, который гарантирует, что целевой вызов реализует определенную функциональность.
Такое же поведение может быть достигнуто с использованием наследования, но из-за общего базового класса получается плотная связь, которой можно избежать с помощью интерфейсов.
Полиморфизм зависит от программирования к интерфейсу, а не от реализации.
Существует два преимущества манипулирования объектами исключительно с точки зрения интерфейса, определенного абстрактными классами:
Это значительно уменьшает зависимости между подсистемами, что приводит к этому принципу программирования для интерфейса.
См. Factory шаблон метода для дальнейшего обоснования этого проекта.
Источник: " Шаблоны проектирования: элементы многоразового объектно-ориентированного программного обеспечения" от G.O.F.
Также смотрите: Factory Шаблон. Когда использовать методы factory?
Реальные примеры - это приложения. Один из них:
Для JDBC вы используете интерфейс java.sql.Connection
. Однако каждый драйвер JDBC обеспечивает собственную реализацию Connection
. Вам не нужно ничего знать о конкретной реализации, потому что она соответствует интерфейсу Connection
.
Еще один из фреймворков java collections. Существует интерфейс java.util.Collection
, который определяет методы size
, add
и remove
(среди многих других). Таким образом, вы можете использовать все типы коллекций взаимозаменяемо. Скажем, у вас есть следующее:
public float calculateCoefficient(Collection collection) {
return collection.size() * something / somethingElse;
}
И еще два метода, которые вызывают это. Один из других методов использует LinkedList
, потому что он более эффективен для этого, а другой использует TreeSet
.
Поскольку оба LinkedList
и TreeSet
реализуют интерфейс Collection
, вы можете использовать только один метод для вычисления коэффициента. Не нужно дублировать код.
И вот идет "программа к интерфейсу" - вам все равно, как именно реализован метод size()
, вы знаете, что он должен вернуть размер коллекции - то есть вы запрограммировали на Collection
а не LinkedList
и TreeSet
в частности.
Но мой совет - найти чтение - возможно, книгу (например, "Мышление в Java" ), - где концепция подробно объясняется.
Каждый объект имеет открытый интерфейс. Коллекция имеет Add
, Remove
, At
и т.д. Сокет может иметь Send
, Receive
, Close
и т.д.
Каждый объект, на который вы действительно можете получить ссылку, имеет конкретную реализацию этих интерфейсов.
Обе эти вещи очевидны, однако то, что несколько менее очевидно...
Ваш код не должен полагаться на детали реализации объекта, только его опубликованный интерфейс.
Если вы делаете это до крайности, вы должны указывать только код Collection<T>
и т.д. (а не ArrayList<T>
). Более того, просто убедитесь, что вы можете заменить что-то концептуально идентичное, не нарушая ваш код.
Чтобы выработать пример Collection<T>
: у вас есть коллекция чего-то, вы на самом деле используете ArrayList<T>
, потому что почему бы и нет. Вы должны убедиться, что код не сломается, если, скажем, вы в конечном итоге используете LinkedList<T>
в будущем.
Здесь сценарий разработки, включающий... pizza:
http://fatagnus.com/program-to-an-interface-not-an-implementation/
"Программирование на интерфейс" происходит, когда вы используете библиотеки, другой код зависит от вашего собственного кода. Затем, как другой код представляет себя для вас, имена методов, его параметры, возвращаемые значения и т.д. Составляют интерфейс, который вы должны запрограммировать. Итак, о том, как вы используете сторонний код.
Это также означает, что вам не нужно заботиться о внутренних компонентах кода, на котором вы зависите, если интерфейс остается прежним, ваш код безопасен (ну, более или менее...)
Технически есть более тонкие детали, такие как языковые концепции, называемые "интерфейсами" в Java, например.
Если вы хотите узнать больше, вы можете спросить, что означает "Реализация интерфейса"...
В основном это означает, что единственная часть библиотеки, которую вы собираетесь использовать, должна опираться на API (интерфейс прикладного программирования) и что вы не должны основывать свое приложение на конкретной реализации библиотеки.
например. Предположим, у вас есть библиотека, которая дает вам stack
. Класс дает вам несколько методов. Скажем, push
, pop
, isempty
и top
. Вы должны написать свое приложение, полагаясь только на них. Один из способов нарушить это заключается в том, чтобы заглянуть внутрь и узнать, что стек реализован с использованием какого-либо массива, так что если вы попадете из пустого стека, вы получите какое-то исключение индекса и затем поймаете это, а не полагаться на метод isempty
, который предоставляет класс. Первый подход не сработает, если поставщик библиотеки переключится с использования массива на использование какого-то списка, в то время как последний все равно будет работать, полагая, что провайдер сохранил свой API, который все еще работает.
Я думаю, что это одна из мантр Эриха Гамма. Я не могу найти первый раз, когда он описал это (до книги GOF), но вы можете видеть, как это обсуждалось в интервью: http://www.artima.com/lejava/articles/designprinciples.html