Что значит программировать на интерфейс? - PullRequest
18 голосов
/ 12 сентября 2009

Я продолжаю слышать утверждение на большинстве сайтов, связанных с программированием:

Программа для интерфейса, а не для Реализация

Но я не понимаю, что это значит?
Примеры помогут.

РЕДАКТИРОВАТЬ: Я получил много хороших ответов, даже если бы вы могли дополнить его фрагментами кода для лучшего понимания предмета. Спасибо!

Ответы [ 17 ]

2 голосов
/ 12 сентября 2009

В 2003 году Аллен Холуб написал замечательную статью для JavaWorld на эту тему под названием Почему расширение - это зло Как он понял из его заголовка, его утверждение «программа для интерфейса» состоит в том, что вы должны успешно реализовывать интерфейсы, но очень редко используете ключевое слово extends для подкласса. Он указывает, среди прочего, на то, что известно как проблема хрупкого базового класса . Из Википедии:

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

2 голосов
/ 12 сентября 2009

В дополнение к другим ответам добавляю еще:

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

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

1 голос
/ 12 сентября 2009

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

Например, многие библиотеки БД выступают в качестве интерфейсов в том смысле, что они могут работать со многими различными действительными БД (MSSQL, MySQL, PostgreSQL, SQLite и т. Д.) Без кода, который использует библиотеку БД, которая вообще должна меняться.

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

1 голос
/ 12 сентября 2009

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

1 голос
/ 12 сентября 2009

Это означает, что ваши переменные, свойства, параметры и возвращаемые типы должны иметь тип интерфейса вместо конкретной реализации.

Это означает, что вы используете IEnumerable<T> Foo(IList mylist) вместо ArrayList Foo(ArrayList myList), например.

Использовать реализацию только при построении объекта:

IList list = new ArrayList();

Если вы сделали это, вы можете позже изменить тип объекта, возможно, позже вы захотите использовать LinkedList вместо ArrayList, это не проблема, так как везде вы называете его просто "IList"

0 голосов
/ 12 февраля 2015

Это в основном то, где вы создаете метод / интерфейс, подобный этому: create( 'apple' ), где метод create(param) происходит от абстрактного класса / интерфейса fruit, который позже реализуется конкретными классами. Это отличается от подклассов. Вы создаете контракт, который должны выполнять классы. Это также уменьшает сцепление и делает вещи более гибкими, когда каждый конкретный класс реализует это по-своему.

Клиентский код не знает о конкретных типах используемых объектов и не знает о классах, которые реализуют эти объекты. Клиентский код знает только об интерфейсе create(param) и использует его для создания фруктовых объектов. Это все равно, что сказать: «Мне все равно, как ты это получишь или сделаешь, я просто хочу, чтобы ты мне это дал».

Аналогия с этим - набор кнопок включения и выключения. Это интерфейс on() и off(). Вы можете использовать эти кнопки на нескольких устройствах, телевизор, радио, свет. Все они обращаются с ними по-разному, но нас это не волнует, все, что нам нужно, это включить или выключить его.

0 голосов
/ 07 января 2015

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

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

enter image description here

Программирование на основе реализации:

Motorcycle motorcycle = new Motorcycle();
motorcycle.driveMoto();

Программирование на основе интерфейса:

Vehicle vehicle;
vehicle = new Motorcycle(); // Note that DI -framework can do it for you
vehicle.drive();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...