Ini mirip dengan jawaban terangkat tetapi saya ingin berpikir keras - mungkin orang lain melihat hal-hal seperti ini juga.
OO Klasik menggunakan konstruktor untuk mendefinisikan kontrak "inisialisasi" publik untuk konsumen kelas (menyembunyikan SEMUA detail implementasi; alias enkapsulasi). Kontrak ini dapat memastikan bahwa setelah instantiasi Anda memiliki objek yang siap digunakan (yaitu tidak ada langkah inisialisasi tambahan untuk diingat (er, dilupakan) oleh pengguna).
(konstruktor) DI tidak dapat dipungkiri memecah encapsulation dengan pendarahan implementasi detail melalui antarmuka konstruktor publik ini. Selama kami masih menganggap konstruktor publik yang bertanggung jawab untuk menentukan kontrak inisialisasi untuk pengguna, kami telah menciptakan pelanggaran enkapsulasi yang mengerikan.
Contoh Teoritis:
Class Foo memiliki 4 metode dan membutuhkan integer untuk inisialisasi, sehingga konstruktornya terlihat seperti Foo (ukuran int) dan segera jelas bagi pengguna kelas Foo bahwa mereka harus memberikan ukuran pada instantiasi agar Foo dapat berfungsi.
Katakanlah implementasi khusus Foo ini mungkin juga memerlukan IWidget untuk melakukan tugasnya. Injeksi konstruktor dari dependensi ini meminta kami membuat konstruktor seperti Foo (ukuran int, widget IWidget)
Apa yang mengganggu saya tentang ini adalah sekarang kita memiliki konstruktor yang memadukan data inisialisasi dengan dependensi - satu input menarik bagi pengguna kelas ( ukuran ), yang lain adalah ketergantungan internal yang hanya berfungsi untuk membingungkan pengguna dan merupakan implementasi detail ( widget ).
Parameter ukuran BUKAN ketergantungan - itu sederhana nilai inisialisasi per-instance. IoC bagus untuk dependensi eksternal (seperti widget) tetapi tidak untuk inisialisasi keadaan internal.
Lebih buruk lagi, bagaimana jika Widget hanya diperlukan untuk 2 dari 4 metode pada kelas ini; Saya mungkin mengeluarkan overhead instantiation untuk Widget meskipun mungkin tidak digunakan!
Bagaimana cara kompromi / rekonsiliasi ini?
Salah satu pendekatan adalah beralih secara eksklusif ke antarmuka untuk menentukan kontrak operasi; dan menghapus penggunaan konstruktor oleh pengguna. Agar konsisten, semua objek harus diakses melalui antarmuka saja, dan dipakai hanya melalui beberapa bentuk resolver (seperti wadah IOC / DI). Hanya wadah yang bisa instantiate hal.
Itu menangani ketergantungan Widget, tetapi bagaimana kita menginisialisasi "ukuran" tanpa menggunakan metode inisialisasi terpisah pada antarmuka Foo? Menggunakan solusi ini, kami kehilangan kemampuan untuk memastikan bahwa instance Foo diinisialisasi penuh pada saat Anda mendapatkan instance. Nyebelin, karena saya sangat suka ide dan kesederhanaan injeksi konstruktor.
Bagaimana cara mencapai inisialisasi dijamin di dunia DI ini, ketika inisialisasi LEBIH dari HANYA ketergantungan eksternal?