Sebenarnya, cara yang "benar" adalah untuk TIDAK menggunakan pabrik sama sekali kecuali sama sekali tidak ada pilihan lain (seperti dalam pengujian unit dan mengejek tertentu - untuk kode produksi Anda TIDAK menggunakan pabrik)! Melakukannya sebenarnya adalah anti-pola dan harus dihindari dengan cara apa pun. Inti dari wadah DI adalah untuk memungkinkan gadget melakukan pekerjaan untuk Anda.
Seperti yang dinyatakan di atas dalam posting sebelumnya, Anda ingin gadget IoC Anda memikul tanggung jawab untuk pembuatan berbagai objek dependen di aplikasi Anda. Itu berarti membiarkan gadget DI Anda membuat dan mengelola berbagai instance itu sendiri. Ini adalah seluruh titik di belakang DI - objek Anda harus TIDAK PERNAH tahu cara membuat dan / atau mengelola objek yang mereka andalkan. Untuk melakukan sebaliknya istirahat longgar kopling.
Mengonversi aplikasi yang sudah ada ke semua DI adalah langkah besar, tetapi mengesampingkan kesulitan yang jelas dalam melakukannya, Anda juga ingin (hanya untuk membuat hidup Anda sedikit lebih mudah) untuk menjelajahi alat DI yang akan melakukan sebagian besar binding Anda secara otomatis (inti dari sesuatu seperti Ninject adalah "kernel.Bind<someInterface>().To<someConcreteClass>()"
panggilan yang Anda buat untuk mencocokkan deklarasi antarmuka Anda dengan kelas-kelas konkret yang ingin Anda gunakan untuk mengimplementasikan antarmuka tersebut. Panggilan "Bind" itulah yang memungkinkan gadget DI Anda untuk mencegat panggilan konstruktor dan menyediakan instances objek dependen yang diperlukan.Sebuah konstruktor khas (kode semu yang ditampilkan di sini) untuk beberapa kelas mungkin:
public class SomeClass
{
private ISomeClassA _ClassA;
private ISomeOtherClassB _ClassB;
public SomeClass(ISomeClassA aInstanceOfA, ISomeOtherClassB aInstanceOfB)
{
if (aInstanceOfA == null)
throw new NullArgumentException();
if (aInstanceOfB == null)
throw new NullArgumentException();
_ClassA = aInstanceOfA;
_ClassB = aInstanceOfB;
}
public void DoSomething()
{
_ClassA.PerformSomeAction();
_ClassB.PerformSomeOtherActionUsingTheInstanceOfClassA(_ClassA);
}
}
Perhatikan bahwa tidak ada tempat di dalam kode itu adalah kode apa pun yang membuat / mengelola / merilis baik instance SomeConcreteClassA atau SomeOtherConcreteClassB. Faktanya, tidak ada kelas konkret yang direferensikan. Jadi ... di mana keajaiban itu terjadi?
Di bagian permulaan aplikasi Anda, hal-hal berikut terjadi (sekali lagi, ini adalah kode semu tetapi cukup dekat dengan hal (Ninject) yang sebenarnya ...):
public void StartUp()
{
kernel.Bind<ISomeClassA>().To<SomeConcreteClassA>();
kernel.Bind<ISomeOtherClassB>().To<SomeOtherConcreteClassB>();
}
Sedikit kode di sana memberitahu Ninject gadget untuk mencari konstruktor, memindai mereka, mencari contoh antarmuka yang telah dikonfigurasikan untuk menangani (itulah panggilan "Bind") dan kemudian membuat dan mengganti instance kelas beton di mana pun instance dirujuk.
Ada alat bagus yang melengkapi Ninject dengan sangat baik yang disebut Ninject.Extensions.Conventions (paket NuGet lain) yang akan melakukan sebagian besar pekerjaan ini untuk Anda. Bukan untuk mengambil dari pengalaman belajar yang luar biasa yang akan Anda lalui saat Anda membangun ini sendiri, tetapi untuk memulai, ini mungkin merupakan alat untuk menyelidiki.
Jika ingatanku, Unity (secara resmi dari Microsoft sekarang merupakan proyek Open Source) memiliki satu atau dua pemanggilan metode yang melakukan hal yang sama, alat lain memiliki pembantu yang serupa.
Apa pun jalur yang Anda pilih, bacalah buku Mark Seemann untuk sebagian besar pelatihan DI Anda, namun, harus ditunjukkan bahwa bahkan "Yang Luar Biasa" dari dunia rekayasa perangkat lunak (seperti Mark) dapat membuat kesalahan mencolok - Mark lupa semua tentang Ninject dalam bukunya jadi di sini adalah sumber daya lain yang ditulis hanya untuk Ninject. Saya memilikinya dan ini adalah bacaan yang bagus: Menguasai Ninject untuk Dependency Injection