По-перше, зрозумійте, що суто абстрактний клас насправді є просто інтерфейсом, який не може зробити багатократне успадкування.
Клас запису, інтерфейс вилучення - це мозкова діяльність, що мертва. Настільки, що ми маємо для цього рефакторинг. Що шкода. Після цього "кожен клас отримує інтерфейс" шаблон не тільки створює безлад, він повністю пропускає крапку.
Інтерфейс не слід вважати просто формальним переглядом того, що може зробити клас. Інтерфейс слід розглядати як контракт, накладений за допомогою коду клієнта, що деталізує його потреби.
У мене взагалі не виникає проблем із написанням інтерфейсу, який наразі має лише один клас для його реалізації. Мені насправді байдуже, чи ще жоден клас не реалізує його. Тому що я думаю про те, що потрібно для мого використання коду. Інтерфейс виражає те, чого вимагає використання коду. Що пізніше відбуватиметься, може робити те, що йому подобається, якщо це задовольнить ці очікування.
Тепер я цього не роблю щоразу, коли один об’єкт використовує інший. Я роблю це при перетині кордону. Я це роблю, коли я не хочу, щоб один об’єкт точно знав, з яким іншим об’єктом йде мова. Це єдиний спосіб спрацювання поліморфізму. Я це роблю, коли очікую, що об'єкт, про який говорить мій клієнт, може змінитись. Я, звичайно, цього не роблю, коли я використовую клас String. Клас String хороший і стабільний, і я не відчуваю потреби в тому, щоб він мінявся на ньому.
Якщо ви вирішили безпосередньо взаємодіяти з конкретною реалізацією, а не через абстракцію, ви прогнозуєте, що реалізація є достатньо стабільною, щоб довіряти, що вона не зміниться.
Саме так є спосіб, яким я гартую принцип інверсії залежності . Не слід сліпо фанатично застосовувати це до всього. Додаючи абстракцію, ви дійсно говорите, що не довіряєте вибору класу-виконавця, щоб бути стабільним протягом життя проекту.
Це все передбачає, що ви намагаєтесь дотримуватися принципу відкритого закритого типу . Цей принцип важливий лише тоді, коли витрати, пов'язані з внесенням прямих змін до встановленого коду, значні. Однією з головних причин людей не погоджуються з тим, наскільки важливими є об'єкти роз'єднання, тому що не кожен зазнає однакових витрат при здійсненні прямих змін. Якщо повторне тестування, перекомпіляція та перерозподіл всієї вашої бази кодів є для вас дрібницею, то вирішення потреби в зміні за допомогою прямої модифікації, ймовірно, буде дуже привабливим спрощенням цієї проблеми.
На це питання просто не знайдено мертвої відповіді. Інтерфейс чи абстрактний клас - це не те, що слід додати до кожного класу, і ви не можете просто підрахувати кількість класів, що реалізуються, і вирішити, що це не потрібно. Йдеться про боротьбу зі змінами. Що означає, що ви передчуваєте майбутнє. Не дивуйтеся, якщо ви помиляєтесь. Зробіть так просто, як не можете, не повертаючись у кут.
Тож, будь ласка, не пишіть абстракції лише для того, щоб допомогти нам прочитати код. Для цього у нас є інструменти. Використовуйте абстракції, щоб відокремити те, що потрібно для розв’язки.