Це гарне запитання - але в певний момент капсулювання в найчистішому вигляді потрібно порушувати, якщо об'єкт коли-небудь матиме свою залежність. Деякий постачальник залежності повинен знати як те, що відповідний об'єкт вимагає Foo
, так і постачальник повинен мати спосіб надання Foo
об'єкта.
Класично цей останній випадок обробляється, як ви кажете, за допомогою аргументів конструктора або методів встановлення. Однак це не обов'язково вірно - я знаю, що останні версії фреймворку Spring DI в Java, наприклад, дозволяють вам анотувати приватні поля (наприклад, з @Autowired
), і залежність буде встановлена за допомогою відображення, не потребуючи викриття залежності через будь-який із класів публічних методів / конструкторів. Це може бути таке рішення, яке ви шукали.
Однак, я не думаю, що введення конструктора теж не є великою проблемою. Я завжди вважав, що об'єкти повинні бути повністю дійсними після побудови, так що все, що їм потрібно для виконання своєї ролі (тобто бути у дійсному стані), все одно повинно подаватися через конструктор. Якщо у вас є об’єкт, для якого потрібен співпрацювач, мені здається прекрасним, що конструктор публічно рекламує цю вимогу і забезпечує її виконання, коли створюється новий екземпляр класу.
В ідеалі, працюючи з об'єктами, ви все одно взаємодієте з ними через інтерфейс, і чим більше ви це робите (і маєте залежності, що проводяться через DI), тим менше ви насправді самі маєте справу з конструкторами. В ідеальній ситуації ваш код не стосується і навіть не створює конкретних примірників класів; тому він просто отримує IFoo
через DI, не турбуючись про те, що конструктор FooImpl
вказує, що він повинен виконувати свою роботу, і насправді, навіть не усвідомлюючи FooImpl
існування Росії. З цієї точки зору, капсулювання є ідеальним.
Це, звичайно, думка, але, на мій погляд, DI не обов'язково порушує інкапсуляцію і насправді може допомогти їй, централізуючи в одному місці всі необхідні знання внутрішніх справ. Це не тільки сама по собі хороша річ, але ще краще, що це місце знаходиться поза вашою власною базою кодів, тому жоден з кодів, які ви пишете, не повинен знати про залежності класів.