OOP: Які існують ситуації, коли дизайн на основі класу кращий за інтерфейс?


10

Я читав веб-сайт JDOM .

Чому API JDOM визначається з точки зору конкретних класів, а не інтерфейсів?

Джейсон Хантер узагальнює аргументи проти інтерфейсу API для JDOM:

З інтерфейсами все стає фабрично, елементи потрібно "імпортувати" в нові документи, а не просто додавати, такі функції, як довгострокова серіалізація, не можна гарантувати, і список продовжується.

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

Я дизайнер-початківець. Усі поради, про які я чув до цього часу, - це застереження від використання дизайну з конкретними класами.

Можливо, використання конкретних занять доречно в певних місцях. Чи є загальні проблеми класу, для яких нормально використовувати конкретні класи в дизайні?


Ви можете поглянути на це: javaworld.com/javaworld/jw-09-2001/jw-0921-interface.html
NoChance

Ви також можете переглянути серію "Обмежити свої абстракції": ayende.com/blog/153889/…
henginy

"Ми це зробили, і дизайн був для цього набагато кращим". - як було краще?
CodeART

Відповіді:


6
  • Спадкування створює залежності від впровадження , що може бути великою проблемою щодо ремонтопридатності. Наслідком цього є те, що ви можете безпечно використовувати успадкування та конкретні класи при роботі з об’єктом передачі даних , які за визначенням майже не містять реалізації. Ви також можете використовувати успадкування конкретних класів, коли вам потрібна ця залежність. У цій ситуації ви можете використовувати абстрактний клас, що містить загальні методи (як правило, корисні функції) у верхній частині ієрархії.
  • Використовуючи конкретну ієрархію класів, не забудьте застосувати Принцип заміщення Ліскова .
  • Немає проблем із використанням конкретних класів для клієнтів (тобто класів, які використовують, а не класів, які використовуються).
  • ІМХО можна використовувати конкретні заняття, поки не зміниться щось. Принцип відкритого / закритого підказує вам використовувати інтерфейси, щоб уникнути з'єднання, але щодо принципу " Вам не знадобиться", ви можете розглянути можливість використання конкретних класів до моменту, коли вам потрібно щось змінити в реалізації. Проблема полягає в тому, що вам доведеться міняти кожного клієнта своїх занять у перший раз, коли щось десь змінюється. Поки у вас є лише один можливий інструмент, щоб щось зробити, ви можете використовувати конкретні класи IMO.

[EDIT] Веб-сайт JDOM є прикладом java.io.File, але це, безумовно, дизайн на основі інтерфейсу, оскільки можна маніпулювати екземпляром java.io.File так, ніби це лише серіалізація. У цій ситуації конкретний клас знали б лише "творці"


Існує два суперечливих визначення поняття "об'єкт цінності", що плаває навколо. Здається, ваш менш поширений, також відомий як "об'єкт передачі даних".
Майкл Боргвардт

@MichaelBorgwardt Thx для вказівки на це, оскільки я мав на увазі не лише "об'єкт передачі даних": я редагую свою відповідь
Маттіас Жуан

1
LSP важливий для будь-яких підтипових відносин, реалізації інтерфейсу, а також успадкування.

3

З сайту JDOM:

Джейсон (Мисливець) заснував проект JDOM на початку 2000 року разом з Бреттом Маклафліном

Тобто, приблизно в той час, коли Java 1.3 була представлена. Щодо розвитку Java не було нічого на шляху зрілості - найдосвідченіші розробники мали лише 4 роки використання Java у кращому випадку. Не було широко використовуваних контейнерів IoC, немає сплячого режиму. Apache Struts тільки починав свій початок.

Що все означає, що Джейсон та Бретт помилялися. Дуже багато людей ще не «зрозуміли». Якщо вони мали C ++ фони, ну, вам не потрібні інтерфейси в C ++ (ну, вони там були в C ++, але вони вам насправді не потрібні, правда?), Навіщо чортів використовувати їх на Java? Що ж, є багато вагомих причин, до яких можуть вас направити інші.

Вони точно не помилялися

все, що можна зробити з інтерфейсами, можна зробити з підкласом

Java не дозволяє множинне успадкування класів, але вона дозволяє реалізувати декілька інтерфейсів. Це може по-справжньому змінити.


3

Згадайте, що стосується вашого питання, що в розробці програмного забезпечення існує кілька способів вирішити проблему, і якщо якийсь розробник використовує техніку, відмінну від вашої, це не означає, що рішення невірне.

Одним із таких випадків є "інтерфейси" проти (базові) "класи". Бувають ситуації, коли однакову мету можна досягти обома методами.

Щоб зробити речі більш складними, є декілька застосувань інтерфейсів, просто зазначимо:

  • один - розробити "контракт" або "специфікацію" без "реалізації"
  • інше, щоб додати функціональність існуючому , а не новому, класу чи ієрархії класів
  • доповнює попередні, щоб дозволити спільний доступ між різними об'єктами, технологіями, наприклад: Enterprise Beans, CORBA, COM, WebServices
  • наслідувати багаторазове успадкування

Ваше питання стосується першого пункту.

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

І залиште інтерфейси для інших сценаріїв.

Хороший приклад - бібліотеки віджетів (елементів керування).

Я пропоную поглянути на інші мови програмування, як вони використовують інтерфейси та класи, такі як: PHP, Delphi (Object Pascal), C #.

Ура.


1

Правила проектування API - це дійсно конкретна річ. Я не впевнений, що вам слід зробити що-небудь із цього поширеного запитання з точки зору того, як ви повинні розробляти свій щоденний код.

Для вашого звичайного коду все-таки вірно, що ви будете використовувати інтерфейс чи спадкове абстрагування класу набагато частіше, ніж IMO про спадкування ванілі.

Щоб добре зрозуміти це правило, ви повинні розміщувати себе не з позиції похідного класу проти його надкласу, а з точки зору об'єкта, який має залежність від іншого об'єкта. Майже завжди краще залежати від абстракції, а не від конкретної реалізації, оскільки це дозволяє прийняти цілу низку різних класів як залежності, спираючись на їх контракт, а не на деталі їх впровадження.

Перше використання для цього часто відбувається в одиничних тестах - якщо ви дійсно хочете одиничне тестування свого класу в повній ізоляції, ви робите це проти фальшивих реалізацій залежностей, які відрізняються від реальних реалізацій, які будуть використовуватися у виробництві.


0

Як правило, ви бажаєте інтерфейс для всього, що передається як параметр або повертається, по суті, щоб ви могли роз'єднати клас від його залежностей.

Так, якщо ми шукаємо клас, ми ніколи не переходимо до винятків, як правило, виключення. Я не розробник Java, але, безумовно, в інших подібних мовах я не думаю, що я бачив інтерфейси, визначені для виключень.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.