Ini bertujuan untuk menjadi jawaban pelengkap bagi Doc Brown, dan juga untuk menanggapi komentar Dinaiz yang belum terjawab yang masih terkait dengan Pertanyaan tersebut.
Apa yang mungkin Anda butuhkan adalah kerangka kerja untuk melakukan DI. Memiliki hierarki yang kompleks tidak harus berarti desain yang buruk, tetapi jika Anda harus menyuntikkan bottom-up TimeFactory (dari A ke D) alih-alih menyuntikkan langsung ke D, maka mungkin ada sesuatu yang salah dengan cara Anda melakukan Injeksi Ketergantungan.
Singleton? Tidak, terima kasih. Jika Anda hanya perlu satu istance untuk membagikannya di seluruh konteks aplikasi Anda (Menggunakan wadah IoC untuk DI seperti Infector ++ hanya perlu untuk mengikat TimeFactory sebagai istance tunggal), berikut ini contohnya (C ++ 11 omong-omong, tapi begitu C ++. Mungkin pindah to C ++ 11 sudah? Anda mendapatkan aplikasi Anti Bocor gratis):
Infector::Container ioc; //your app's context
ioc.bindSingleAsNothing<TimeFactory>(); //declare TimeFactory to be shared
ioc.wire<TimeFactory>(); //wire its constructor
// if you want to be sure TimeFactory is created at startup just request it
// (else it will be created lazily only when needed)
auto myTimeFactory = ioc.buildSingle<TimeFactory>();
Sekarang poin bagus dari wadah IoC adalah Anda tidak perlu melewatkan waktu pabrik hingga D. jika kelas "D" Anda membutuhkan waktu pabrik, cukup cantumkan pabrik waktu sebagai parameter konstruktor untuk kelas D.
ioc.bindAsNothing<A>(); //declare class A
ioc.bindAsNothing<B>(); //declare class B
ioc.bindAsNothing<D>(); //declare class D
//constructors setup
ioc.wire<D, TimeFactory>(); //time factory injected to class D
ioc.wire<B, D>(); //class D injected to class B
ioc.wire<A, B>(); //class B injected to class A
seperti yang Anda lihat Anda menyuntikkan TimeFactory hanya sekali. Bagaimana cara menggunakan "A"? Sangat sederhana, setiap kelas diinjeksi, dibangun di main atau di-istantiated dengan pabrik.
auto myA1 = ioc.build<A>(); //A is not "single" so many different istances
auto myA2 = ioc.build<A>(); //can live at same time
setiap kali Anda membuat kelas A itu akan secara otomatis (lazy istantiation) disuntikkan dengan semua dependensi hingga D dan D akan disuntikkan dengan TimeFactory, jadi dengan memanggil hanya 1 metode, Anda sudah siap dengan hierarki lengkap Anda (dan bahkan hierarki kompleks diselesaikan dengan cara ini) menghapus BANYAK kode pelat ketel): Anda tidak perlu memanggil "baru / hapus" dan itu sangat penting karena Anda dapat memisahkan logika aplikasi dari kode lem.
D dapat membuat objek Waktu dengan informasi yang hanya dapat dimiliki D
Itu mudah, TimeFactory Anda memiliki metode "buat", lalu gunakan saja tanda tangan berbeda "buat (params)" dan Anda selesai. Parameter yang tidak ada dependensi sering diselesaikan dengan cara ini. Ini juga menghilangkan tugas menyuntikkan hal-hal seperti "string" atau "bilangan bulat" karena itu hanya menambah pelat ketel tambahan.
Siapa yang menciptakan siapa? Kontainer IoC menciptakan pabrik dan pabrik, pabrik menciptakan sisanya (pabrik dapat membuat objek yang berbeda dengan parameter sewenang-wenang, sehingga Anda tidak benar-benar memerlukan keadaan untuk pabrik). Anda masih dapat menggunakan pabrik sebagai pembungkus untuk Kontainer IoC: secara umum, menyuntikkan Kontainer IoC sangat buruk dan sama dengan menggunakan pencari lokasi layanan. Beberapa orang memecahkan masalah dengan membungkus Kontainer IoC dengan sebuah pabrik (ini tidak sepenuhnya diperlukan, tetapi memiliki keuntungan bahwa hierarki diselesaikan oleh Kontainer dan semua pabrik Anda menjadi lebih mudah dipelihara).
//factory method
std::unique_ptr<myType> create(params){
auto istance = ioc->build<myType>(); //this code's agnostic to "myType" hierarchy
istance->setParams(params); //the customization you needed
return std::move(istance);
}
Juga jangan menyalahgunakan injeksi ketergantungan, tipe sederhana hanya bisa menjadi anggota kelas atau variabel cakupan lokal. Ini tampak jelas tetapi saya melihat orang menyuntikkan "std :: vector" hanya karena ada kerangka kerja DI yang memungkinkan. Selalu ingat hukum Demeter: "Suntikkan hanya apa yang benar-benar Anda butuhkan untuk disuntikkan"