Apa itu injeksi ketergantungan?

3075

Ada beberapa pertanyaan yang sudah diposting dengan pertanyaan spesifik tentang injeksi ketergantungan , seperti kapan menggunakannya dan kerangka apa yang ada untuk itu. Namun,

Apa itu injeksi ketergantungan dan kapan / mengapa harus atau tidak harus digunakan?

AR.
sumber
Lihat diskusi saya tentang Injeksi Ketergantungan Di Sini .
Kevin S.
33
Saya setuju dengan komentar tentang tautan. Saya bisa mengerti Anda mungkin ingin referensi orang lain. Tapi setidaknya tambahkan mengapa Anda menautkannya dan apa yang membuat tautan ini lebih baik daripada tautan lain yang bisa saya dapatkan dengan menggunakan google
Christian Payne
@ AAR: Secara teknis, Ketergantungan Injeksi bukanlah bentuk khusus dari IOC. Sebaliknya, IoC adalah salah satu teknik yang digunakan untuk memberikan Injeksi Ketergantungan. Teknik-teknik lain dapat digunakan untuk menyediakan Injeksi Ketergantungan (walaupun IoC adalah satu-satunya yang umum digunakan), dan IoC digunakan untuk banyak masalah lain juga.
Sean Reilly
Salah satu penjelasan terindah yang pernah saya baca tentang DI adalah dari Google's Guice (diucapkan sebagai jus) http://code.google.com/p/google-guice/wiki/Motivation?tm=6
Raj
136
Mengenai tautan, ingatlah bahwa tautan sering menghilang dengan satu atau lain cara. Ada semakin banyak tautan mati dalam jawaban SO. Jadi, tidak peduli seberapa bagus artikel yang ditautkan, tidak ada gunanya sama sekali jika Anda tidak dapat menemukannya.
DOK

Jawaban:

1931

Dependency Injection adalah meneruskan ketergantungan pada objek atau kerangka kerja lain (dependency injector).

Ketergantungan injeksi membuat pengujian lebih mudah. Injeksi dapat dilakukan melalui konstruktor .

SomeClass() memiliki konstruktor sebagai berikut:

public SomeClass() {
    myObject = Factory.getObject();
}

Masalah : Jika myObjectmelibatkan tugas kompleks seperti akses disk atau akses jaringan, sulit untuk melakukan pengujian unit SomeClass(). Pemrogram harus mengejek myObjectdan mungkin mencegat panggilan pabrik.

Solusi alternatif :

  • Melewati myObjectsebagai argumen ke konstruktor
public SomeClass (MyClass myObject) {
    this.myObject = myObject;
}

myObject dapat dilewati secara langsung yang membuat pengujian lebih mudah.

  • Salah satu alternatif umum adalah mendefinisikan konstruktor do-nothing . Injeksi ketergantungan dapat dilakukan melalui setter. (h / t @MikeVella).
  • Martin Fowler mendokumentasikan alternatif ketiga (h / t @MarcDix), di mana kelas secara eksplisit mengimplementasikan antarmuka untuk dependensi yang ingin disuntikkan oleh programmer.

Lebih sulit untuk mengisolasi komponen dalam pengujian unit tanpa injeksi ketergantungan.

Pada 2013, ketika saya menulis jawaban ini, ini adalah tema utama di Google Testing Blog . Ini tetap menjadi keuntungan terbesar bagi saya, karena programmer tidak selalu membutuhkan fleksibilitas ekstra dalam desain run-time mereka (misalnya, untuk pencari lokasi atau pola serupa). Pemrogram sering perlu mengisolasi kelas selama pengujian.

wds
sumber
25
Mengakui bahwa referensi Ben Hoffstein untuk artikel Martin Fowler diperlukan untuk menunjukkan 'harus dibaca' pada subjek, saya menerima jawaban wds 'karena itu sebenarnya menjawab pertanyaan di SO.
AR.
121
+1 untuk penjelasan dan motivasi: membuat kreasi objek yang menjadi dasar kelas tergantung masalah orang lain . Cara lain untuk mengatakannya adalah DI membuat kelas lebih kohesif (mereka memiliki tanggung jawab lebih sedikit).
Fuhrmanator
13
Anda mengatakan ketergantungan dilewatkan "ke konstruktor" tetapi seperti yang saya mengerti ini tidak sepenuhnya benar. Itu masih ketergantungan injeksi jika ketergantungan ditetapkan sebagai properti setelah objek telah dipakai, benar?
Mike Vella
1
@ Mike Vella Ya, itu benar. Tidak ada perbedaan nyata dalam kebanyakan kasus, meskipun properti umumnya sedikit lebih fleksibel. Saya akan mengedit teks sedikit untuk menunjukkan itu.
wds
2
Salah satu jawaban terbaik yang saya temukan sejauh ini, jadi saya benar-benar tertarik untuk memperbaikinya. Tidak ada deskripsi bentuk injeksi ketergantungan ketiga: Antarmuka injeksi .
Marc Dix
2351

Definisi terbaik yang saya temukan sejauh ini adalah satu oleh James Shore :

"Injeksi Ketergantungan" adalah istilah 25 dolar untuk konsep 5 sen. [...] Injeksi ketergantungan berarti memberikan objek variabel instan ke objek. [...]

Ada sebuah artikel oleh Martin Fowler yang mungkin terbukti bermanfaat juga.

Ketergantungan injeksi pada dasarnya menyediakan objek yang dibutuhkan suatu objek (dependensinya) alih-alih membuatnya membangunnya sendiri. Ini adalah teknik yang sangat berguna untuk pengujian, karena memungkinkan dependensi untuk dipermainkan atau dihilangkan.

Ketergantungan dapat disuntikkan ke objek dengan banyak cara (seperti injeksi konstruktor atau injeksi setter). Satu bahkan dapat menggunakan kerangka kerja injeksi ketergantungan khusus (misalnya Spring) untuk melakukan itu, tetapi mereka tentu tidak diperlukan. Anda tidak perlu kerangka kerja itu untuk memiliki injeksi ketergantungan. Instantiating dan meneruskan objek (dependensi) secara eksplisit sama baiknya dengan injeksi oleh kerangka kerja.

Thiago Arrais
sumber
35
Saya suka penjelasan dari artikel James, terutama yang terakhir: "Tetap saja, Anda harus mengagumi pendekatan apa pun yang mengambil tiga konsep ('TripPlanner,' 'CabAgency,' dan 'AirlineAgency'), mengubahnya menjadi sembilan kelas lebih, dan kemudian menambahkan puluhan baris kode lem dan konfigurasi XML sebelum satu baris logika aplikasi ditulis. " Inilah yang sering saya lihat (sedih) - bahwa injeksi ketergantungan (yang bagus seperti yang dijelaskan olehnya) disalahgunakan untuk hal-hal rumit yang bisa dilakukan dengan lebih mudah - akhirnya menulis kode "pendukung" ...
Matt
2
Re: "Instantiating dan meneruskan objek (dependensi) secara eksplisit sama baiknya dengan injeksi dengan kerangka kerja." Jadi mengapa orang membuat kerangka kerja melakukan itu?
dzieciou
13
Untuk alasan yang sama bahwa setiap kerangka kerja (atau setidaknya harus mendapatkan) ditulis: karena ada banyak kode berulang / boilerplate yang perlu ditulis setelah Anda mencapai kompleksitas tertentu. Masalahnya adalah berkali-kali orang akan meraih kerangka bahkan ketika itu tidak benar-benar dibutuhkan.
Thiago Arrais
14
Istilah $ 25 untuk konsep 5 sen sudah mati. Inilah artikel bagus yang membantu saya: codeproject.com/Articles/615139/…
Christine
@Matt file-file konfigurasi hanyalah "Tunda keputusan" yang dibawa secara ekstrem - "Tunda keputusan sampai runtime yang sebenarnya". Belati dan terutama Belati menurut saya menemukan sweet spot "Tunda keputusan sampai waktu perakitan aplikasi".
Thorbjørn Ravn Andersen
645

Saya menemukan contoh lucu ini dalam hal kopling longgar :

Aplikasi apa pun terdiri dari banyak objek yang saling berkolaborasi untuk melakukan beberapa hal berguna. Secara tradisional setiap objek bertanggung jawab untuk mendapatkan referensi sendiri ke objek dependen (dependensi) yang dikolaborasikan dengannya. Ini mengarah ke kelas yang sangat berpasangan dan kode yang sulit untuk diuji.

Sebagai contoh, pertimbangkan Carobjek.

A Cartergantung pada roda, mesin, bahan bakar, baterai, dll untuk menjalankan. Secara tradisional kita mendefinisikan merek dari objek dependen tersebut bersama dengan definisi Carobjek.

Tanpa Injeksi Ketergantungan (DI):

class Car{
  private Wheel wh = new NepaliRubberWheel();
  private Battery bt = new ExcideBattery();

  //The rest
}

Di sini, Carobjek bertanggung jawab untuk membuat objek dependen.

Bagaimana jika kita ingin mengubah jenis objek dependennya - katakan Wheel- setelah NepaliRubberWheel()tusukan awal ? Kita perlu membuat ulang objek Mobil dengan ketergantungan baru ChineseRubberWheel(), tetapi hanya Carpabrikan yang bisa melakukannya.

Lalu apa gunanya Dependency Injectionbagi kita ...?

Saat menggunakan injeksi dependensi, objek diberi dependensinya pada waktu berjalan daripada waktu kompilasi (waktu pembuatan mobil) . Sehingga kita sekarang dapat mengubah Wheelkapan saja kita mau. Di sini, dependency( wheel) dapat disuntikkan ke Cardalam waktu berjalan.

Setelah menggunakan injeksi ketergantungan:

Di sini, kita suntik yang dependensi (roda dan Battery) pada saat runtime. Karena itu istilahnya: Injeksi Ketergantungan.

class Car{
  private Wheel wh; // Inject an Instance of Wheel (dependency of car) at runtime
  private Battery bt; // Inject an Instance of Battery (dependency of car) at runtime
  Car(Wheel wh,Battery bt) {
      this.wh = wh;
      this.bt = bt;
  }
  //Or we can have setters
  void setWheel(Wheel wh) {
      this.wh = wh;
  }
}

Sumber: Memahami injeksi ketergantungan

gtiwari333
sumber
20
Cara saya memahami hal ini adalah, alih-alih membuat instance objek baru sebagai bagian dari objek lain, kita dapat menyuntikkan objek tersebut kapan dan jika diperlukan sehingga menghilangkan ketergantungan objek pertama pada objek tersebut. Apakah itu benar?
JeliBeanMachine
Saya telah menggambarkan ini dengan contoh coffee shop di sini: digigene.com/design-patterns/dependency-injection-coffeeshop
Ali Nem
11
Sangat suka analogi ini karena ini bahasa Inggris yang sederhana menggunakan analogi sederhana. Mengatakan aku Toyota, sudah menghabiskan terlalu banyak finansial dan tenaga untuk membuat mobil dari desain untuk bergulir dari merakit baris, jika ada ada produsen ban terkemuka, mengapa saya harus mulai dari awal untuk membuat sebuah divisi ban manufaktur yaitu untuk newsebuah ban? Bukan saya. Yang harus saya lakukan adalah membeli (menyuntikkan melalui param) dari mereka, menginstal dan wah-lah! Jadi, kembali ke pemrograman, katakanlah proyek C # perlu menggunakan perpustakaan / kelas yang ada, ada dua cara untuk menjalankan / men-debug, 1-tambah referensi ke seluruh proyek ini
Jeb50
(tidak), .. perpustakaan / kelas eksternal, atau 2-tambahkan dari DLL. Kecuali kita harus melihat apa yang ada di dalam kelas eksternal ini, menambahkannya sebagai DLL adalah cara yang lebih mudah. Jadi opsi 1 adalah untuk newitu, opsi 2 meneruskannya sebagai param. Mungkin tidak akurat, tapi bodoh sederhana mudah dimengerti.
Jeb50
1
@JeliBeanMachine (maaf atas keterlambatan membalas komentar ..) bukan karena kita menghapus ketergantungan objek pertama pada objek roda atau objek baterai, melainkan bahwa kita meneruskan dependensi, sehingga kita dapat mengubah instance atau implementasi dari ketergantungan. Sebelumnya: Mobil memiliki ketergantungan pada hardcod pada NepaliRubberWheel. Setelah: Mobil memiliki ketergantungan yang disuntikkan pada instance dari Wheel.
Mikael Ohlson
263

Dependency Injection adalah praktik di mana objek dirancang dengan cara di mana mereka menerima instance objek dari potongan kode lain, alih-alih membangunnya secara internal. Ini berarti bahwa objek apa pun yang mengimplementasikan antarmuka yang diperlukan oleh objek dapat diganti tanpa mengubah kode, yang menyederhanakan pengujian, dan meningkatkan decoupling.

Sebagai contoh, pertimbangkan klausa ini:

public class PersonService {
  public void addManager( Person employee, Person newManager ) { ... }
  public void removeManager( Person employee, Person oldManager ) { ... }
  public Group getGroupByManager( Person manager ) { ... }
}

public class GroupMembershipService() {
  public void addPersonToGroup( Person person, Group group ) { ... }
  public void removePersonFromGroup( Person person, Group group ) { ... }
} 

Dalam contoh ini, implementasi PersonService::addManagerdan PersonService::removeManagerakan membutuhkan instance GroupMembershipServiceuntuk dapat melakukan tugasnya. Tanpa Injeksi Ketergantungan, cara tradisional untuk melakukan ini adalah dengan instantiate yang baru GroupMembershipServicedi konstruktor PersonServicedan menggunakan atribut instance di kedua fungsi. Namun, jika konstruktor GroupMembershipServicememiliki banyak hal yang diperlukan, atau lebih buruk lagi, ada beberapa "setter" inisialisasi yang perlu dipanggil GroupMembershipService, kode tumbuh agak cepat, dan PersonServicesekarang tergantung tidak hanya pada GroupMembershipServicetetapi juga segala sesuatu GroupMembershipServicetergantung pada. Selain itu, tautan ke GroupMembershipServicehardcoded ke dalam PersonServiceyang berarti Anda tidak dapat "dummy"GroupMembershipService untuk tujuan pengujian, atau untuk menggunakan pola strategi di berbagai bagian aplikasi Anda.

Dengan Dependency Injection, alih-alih membuat instance di GroupMembershipServicedalam Anda PersonService, Anda akan meneruskannya ke PersonServicekonstruktor, atau menambahkan Properti (pengambil dan penyetel) untuk menetapkan contoh lokal dari itu. Ini berarti bahwa Anda PersonServicetidak perlu lagi khawatir tentang cara membuat GroupMembershipService, itu hanya menerima yang diberikan, dan bekerja dengan mereka. Ini juga berarti bahwa apa pun yang merupakan subkelas dari GroupMembershipService, atau mengimplementasikan GroupMembershipServiceantarmuka dapat "disuntikkan" ke PersonService, dan PersonServicetidak perlu tahu tentang perubahan itu.

Adam Ness
sumber
29
Akan lebih bagus jika Anda bisa memberikan contoh kode yang sama SETELAH menggunakan DI
CodyBugstein
170

Jawaban yang diterima adalah jawaban yang bagus - tetapi saya ingin menambahkan bahwa DI sangat mirip dengan klasik yang menghindari konstanta hardcode dalam kode.

Ketika Anda menggunakan konstanta seperti nama basis data, Anda akan dengan cepat memindahkannya dari bagian dalam kode ke beberapa file konfigurasi dan meneruskan variabel yang berisi nilai tersebut ke tempat yang diperlukan. Alasan untuk melakukan itu adalah bahwa konstanta ini biasanya berubah lebih sering daripada sisa kode. Misalnya jika Anda ingin menguji kode dalam database pengujian.

DI analog dengan ini dalam dunia pemrograman Berorientasi Objek. Nilai-nilai di sana alih-alih literal konstan adalah objek keseluruhan - tetapi alasan untuk memindahkan kode yang membuatnya dari kode kelas serupa - objek lebih sering berubah daripada kode yang menggunakannya. Satu kasus penting di mana perubahan semacam itu diperlukan adalah tes.

zby
sumber
18
+1 "objek berubah lebih sering daripada kode yang menggunakannya". Untuk menggeneralisasi, tambahkan tipuan pada titik-titik fluks. Tergantung pada titik fluks, tipuan dipanggil dengan nama yang berbeda !!
Chethan
139

Mari kita coba contoh sederhana dengan kelas Mobil dan Mesin , setiap mobil membutuhkan mesin untuk pergi ke mana pun, setidaknya untuk saat ini. Jadi di bawah ini bagaimana kode akan terlihat tanpa injeksi ketergantungan.

public class Car
{
    public Car()
    {
        GasEngine engine = new GasEngine();
        engine.Start();
    }
}

public class GasEngine
{
    public void Start()
    {
        Console.WriteLine("I use gas as my fuel!");
    }
}

Dan untuk membuat instance kelas Mobil kita akan menggunakan kode berikutnya:

Car car = new Car();

Masalah dengan kode ini yang kami gabungkan dengan erat ke GasEngine dan jika kami memutuskan untuk mengubahnya ke ElectricityEngine maka kami perlu menulis ulang kelas Car. Dan semakin besar aplikasinya, semakin banyak masalah dan sakit kepala yang harus kita tambahkan dan gunakan jenis mesin baru.

Dengan kata lain dengan pendekatan ini adalah bahwa kelas mobil tingkat tinggi kami bergantung pada kelas GasEngine tingkat rendah yang melanggar Prinsip Ketergantungan Inversi (DIP) dari SOLID. DIP menyarankan bahwa kita harus bergantung pada abstraksi, bukan kelas yang konkret. Jadi untuk memuaskan ini kami memperkenalkan antarmuka IEngine dan menulis ulang kode seperti di bawah ini:

    public interface IEngine
    {
        void Start();
    }

    public class GasEngine : IEngine
    {
        public void Start()
        {
            Console.WriteLine("I use gas as my fuel!");
        }
    }

    public class ElectricityEngine : IEngine
    {
        public void Start()
        {
            Console.WriteLine("I am electrocar");
        }
    }

    public class Car
    {
        private readonly IEngine _engine;
        public Car(IEngine engine)
        {
            _engine = engine;
        }

        public void Run()
        {
            _engine.Start();
        }
    }

Sekarang kelas Mobil kami hanya bergantung pada antarmuka IEngine, bukan implementasi mesin yang spesifik. Sekarang, satu-satunya trik adalah bagaimana kita membuat turunan dari Mobil dan memberikan kelas Mesin beton yang sebenarnya seperti GasEngine atau ElectricityEngine. Di situlah Dependency Injection masuk.

   Car gasCar = new Car(new GasEngine());
   gasCar.Run();
   Car electroCar = new Car(new ElectricityEngine());
   electroCar.Run();

Di sini kita pada dasarnya menyuntikkan (meneruskan) ketergantungan kita (contoh mesin) ke konstruktor Mobil. Jadi sekarang kelas kami memiliki kopling longgar antara objek dan dependensinya, dan kami dapat dengan mudah menambahkan jenis mesin baru tanpa mengubah kelas Mobil.

Manfaat utama Injeksi Ketergantungan bahwa kelas lebih longgar digabungkan, karena mereka tidak memiliki dependensi hard-coded. Ini mengikuti Prinsip Ketergantungan Inversi, yang disebutkan di atas. Alih-alih merujuk implementasi spesifik, kelas meminta abstraksi (biasanya antarmuka ) yang diberikan kepada mereka ketika kelas dibangun.

Jadi pada akhirnya injeksi Ketergantungan hanyalah teknik untuk mencapai kopling longgar antara objek dan ketergantungannya. Daripada secara langsung instantiasi dependensi yang dibutuhkan kelas untuk melakukan tindakannya, dependensi disediakan untuk kelas (paling sering) melalui injeksi konstruktor.

Juga ketika kita memiliki banyak dependensi, adalah praktik yang sangat baik untuk menggunakan wadah Inversion of Control (IoC) yang dapat kita beri tahu antarmuka mana yang harus dipetakan ke implementasi konkret mana untuk semua dependensi kita dan kita dapat memilikinya menyelesaikan dependensi tersebut untuk kita ketika ia membangun objek kita. Sebagai contoh, kita dapat menentukan dalam pemetaan untuk wadah IoC bahwa ketergantungan IEngine harus dipetakan ke kelas GasEngine dan ketika kita bertanya wadah IoC untuk instance dari kelas Mobil kami , itu akan secara otomatis membangun kelas Mobil kami dengan ketergantungan GasEngine lewat.

UPDATE: Menonton kursus tentang EF Core dari Julie Lerman baru-baru ini dan juga menyukai definisi singkatnya tentang DI.

Ketergantungan injeksi adalah pola untuk memungkinkan aplikasi Anda menyuntikkan objek dengan cepat ke kelas yang membutuhkannya, tanpa memaksa kelas-kelas tersebut untuk bertanggung jawab atas objek-objek tersebut. Ini memungkinkan kode Anda untuk digabungkan secara lebih longgar, dan Entity Framework Core terhubung ke sistem layanan yang sama ini.

pengguna2771704
sumber
2
hanya karena penasaran, bagaimana ini berbeda dari pola strategi? Pola ini mengenkapsulasi algoritma dan membuatnya dapat dipertukarkan. Rasanya injeksi ketergantungan dan pola strategi sangat mirip.
elixir
110

Bayangkan Anda ingin memancing:

  • Tanpa injeksi ketergantungan, Anda perlu mengurus semuanya sendiri. Anda perlu menemukan perahu, membeli pancing, mencari umpan, dll. Itu mungkin, tentu saja, tetapi menempatkan banyak tanggung jawab pada Anda. Dalam istilah perangkat lunak, itu berarti Anda harus melakukan pencarian untuk semua hal ini.

  • Dengan injeksi ketergantungan, orang lain mengurus semua persiapan dan membuat peralatan yang diperlukan tersedia untuk Anda. Anda akan menerima ("disuntikkan") perahu, pancing, dan umpan - semuanya siap digunakan.

Olivier Liechti
sumber
59
Sisi baiknya adalah, bayangkan Anda menyewa tukang ledeng untuk mengulang kamar mandi Anda, yang kemudian berkata, "Bagus, ini daftar alat dan bahan yang saya butuhkan untuk Anda dapatkan untuk saya". Bukankah itu pekerjaan tukang ledeng?
jscs
Sehingga seseorang perlu merawat beberapa orang yang tidak memiliki bisnis mengetahui .. tetapi masih memutuskan untuk mengumpulkan daftar perahu, tongkat dan umpan - meskipun siap digunakan.
Chookoos
22
@ JoshCaswell Tidak, itu akan menjadi pekerjaan tukang leding tukang ledeng. Sebagai seorang klien, Anda perlu membuat saluran air. Untuk itu Anda perlu tukang ledeng. Tukang ledeng membutuhkan alatnya. Untuk mendapatkannya, itu akan dilengkapi oleh perusahaan plumbing. Sebagai seorang klien Anda tidak ingin tahu persis apa yang tukang ledeng lakukan atau butuhkan. Sebagai tukang ledeng, Anda tahu apa yang Anda butuhkan, tetapi Anda hanya ingin melakukan pekerjaan Anda, bukan mendapatkan segalanya. Sebagai majikan tukang ledeng Anda bertanggung jawab untuk melengkapi tukang ledeng Anda dengan apa yang mereka butuhkan sebelum mengirim mereka ke rumah-rumah penduduk.
sara
@ai saya mengerti maksud Anda. Dalam perangkat lunak kita berbicara tentang pabrik, benar? Tetapi DI juga biasanya berarti kelas tidak menggunakan pabrik karena itu masih belum disuntikkan. Anda, pelanggan, perlu menghubungi majikan (pabrik) untuk memberi Anda alat, sehingga Anda bisa meneruskan ke tukang ledeng. Bukankah itu benar-benar bekerja dalam suatu program? Jadi, sementara pelanggan (kelas panggilan / fungsi / apa pun) tidak harus membeli alat, mereka masih harus menjadi perantara untuk memastikan mereka berhasil sampai ke tukang ledeng (kelas injeksi) dari majikan (pabrik).
KingOfAllTrades
1
@ KingOfAllTrades: Tentu saja pada titik tertentu Anda harus memiliki seseorang yang mempekerjakan dan memasang tukang ledeng, atau Anda tidak memiliki tukang ledeng. Tetapi Anda tidak memiliki pelanggan yang melakukannya. Pelanggan hanya meminta tukang ledeng, dan mendapatkannya sudah dilengkapi dengan apa yang dia butuhkan untuk melakukan pekerjaannya. Dengan DI, Anda akhirnya masih memiliki beberapa kode untuk memenuhi dependensi. Tapi Anda memisahkannya dari kode yang berfungsi nyata. Jika Anda mengambilnya semaksimal mungkin, objek Anda hanya membuat ketergantungannya diketahui, dan objek-grafik-bangunan terjadi di luar, sering kali dalam kode init.
cHao
102

Ini adalah penjelasan paling sederhana tentang Dependency Injection dan Dependency Injection Container yang pernah saya lihat:

Tanpa Injeksi Ketergantungan

  • Aplikasi membutuhkan Foo (misal pengontrol), jadi:
  • Aplikasi menciptakan Foo
  • Aplikasi memanggil Foo
    • Foo membutuhkan Bilah (misalnya layanan), jadi:
    • Foo menciptakan Bar
    • Foo memanggil Bar
      • Bar membutuhkan Bim (layanan, repositori, ...), jadi:
      • Bar menciptakan Bim
      • Bar melakukan sesuatu

Dengan Injeksi Ketergantungan

  • Aplikasi membutuhkan Foo, yang membutuhkan Bar, yang membutuhkan Bim, jadi:
  • Aplikasi menciptakan Bim
  • Aplikasi menciptakan Bar dan memberinya Bim
  • Aplikasi menciptakan Foo dan memberinya Bar
  • Aplikasi memanggil Foo
    • Foo memanggil Bar
      • Bar melakukan sesuatu

Menggunakan Wadah Injeksi Ketergantungan

  • Aplikasi membutuhkan Foo jadi:
  • Aplikasi mendapat Foo dari Container, jadi:
    • Wadah menciptakan Bim
    • Container menciptakan Bar dan memberinya Bim
    • Container menciptakan Foo dan memberinya Bar
  • Aplikasi memanggil Foo
    • Foo memanggil Bar
      • Bar melakukan sesuatu

Ketergantungan Injeksi dan ketergantungan Injeksi Kontainer adalah hal yang berbeda:

  • Ketergantungan Injeksi adalah metode untuk menulis kode yang lebih baik
  • Wadah DI adalah alat untuk membantu menyuntikkan dependensi

Anda tidak perlu wadah untuk melakukan injeksi ketergantungan. Namun sebuah wadah dapat membantu Anda.

Pmpr
sumber
@rootTraveller google adalah teman Anda: Kapan tidak tepat menggunakan pola injeksi ketergantungan?
Pmpr
55

Bukankah "injeksi ketergantungan" hanya berarti menggunakan konstruktor berparameter dan setter publik?

Artikel James Shore menunjukkan contoh-contoh berikut untuk perbandingan .

Konstruktor tanpa injeksi ketergantungan:

public class Example { 
  private DatabaseThingie myDatabase; 

  public Example() { 
    myDatabase = new DatabaseThingie(); 
  } 

  public void doStuff() { 
    ... 
    myDatabase.getData(); 
    ... 
  } 
} 

Pembuat dengan injeksi ketergantungan:

public class Example { 
  private DatabaseThingie myDatabase; 

  public Example(DatabaseThingie useThisDatabaseInstead) { 
    myDatabase = useThisDatabaseInstead; 
  }

  public void doStuff() { 
    ... 
    myDatabase.getData(); 
    ... 
  } 
}
JaneGoodall
sumber
Tentunya dalam versi DI Anda tidak ingin menginisialisasi objek myDatabase di konstruktor tanpa argumen? Tampaknya tidak ada gunanya dan akan berfungsi untuk melemparkan pengecualian jika Anda mencoba memanggil DoStuff tanpa memanggil konstruktor yang kelebihan beban?
Matt Wilko
Hanya jika new DatabaseThingie()tidak menghasilkan instance myDatabase yang valid.
JaneGoodall
40

Untuk membuat konsep Ketergantungan Injeksi mudah dipahami. Mari kita ambil contoh tombol sakelar untuk menghidupkan (mematikan / mematikan) bohlam.

Tanpa Injeksi Ketergantungan

Switch perlu tahu sebelumnya bohlam mana saya terhubung (ketergantungan kode keras). Begitu,

Switch -> PermanentBulb // switch terhubung langsung ke bulb permanen, pengujian tidak mungkin dengan mudah

Switch(){
PermanentBulb = new Bulb();
PermanentBulb.Toggle();
}

Dengan Injeksi Ketergantungan

Switch hanya tahu saya harus menghidupkan / mematikan Bulb mana pun yang diberikan kepada saya. Begitu,

Beralih -> Bulb1 ATAU Bulb2 ATAU NightBulb (ketergantungan disuntikkan)

Switch(AnyBulb){ //pass it whichever bulb you like
AnyBulb.Toggle();
}

Mengubah Contoh James untuk Switch dan Bulb:

public class SwitchTest { 
  TestToggleBulb() { 
    MockBulb mockbulb = new MockBulb(); 

    // MockBulb is a subclass of Bulb, so we can 
    // "inject" it here: 
    Switch switch = new Switch(mockBulb); 

    switch.ToggleBulb(); 
    mockBulb.AssertToggleWasCalled(); 
  } 
}

public class Switch { 
  private Bulb myBulb; 

  public Switch() { 
    myBulb = new Bulb(); 
  } 

  public Switch(Bulb useThisBulbInstead) { 
    myBulb = useThisBulbInstead; 
  } 

  public void ToggleBulb() { 
    ... 
    myBulb.Toggle(); 
    ... 
  } 
}`
wakqasahmed
sumber
36

Apa itu Dependency Injection (DI)?

Seperti yang orang lain katakan, Dependency Injection (DI) menghilangkan tanggung jawab penciptaan langsung, dan manajemen masa hidup, dari instance objek lain yang menjadi dasar ketergantungan kelas kelas kami (kelas konsumen) (dalam arti UML ). Contoh-contoh ini bukannya diteruskan ke kelas konsumen kami, biasanya sebagai parameter konstruktor atau melalui setter properti (pengelolaan objek dependensi yang mem-instans dan meneruskan ke kelas konsumen biasanya dilakukan oleh Inversion of Control (IoC) , tapi itu topik lain) .

DI, DIP dan SOLID

Secara khusus, dalam paradigma prinsip SOLID Obyek Berorientasi Desain Robert C Martin , DIadalah salah satu implementasi yang mungkin dari Dependency Inversion Principle (DIP) . The DIP adalah Ddari SOLIDmantra - implementasi DIP lainnya meliputi Jasa Locator, dan pola Plugin.

Tujuan dari DIP adalah untuk memisahkan ketergantungan yang kuat dan konkret antar kelas, dan sebagai gantinya, melonggarkan kopling melalui abstraksi, yang dapat dicapai melalui interface, abstract classataupure virtual class , tergantung pada bahasa dan pendekatan yang digunakan.

Tanpa DIP, kode kami (saya menyebutnya 'kelas konsumsi') secara langsung digabungkan ke ketergantungan konkret dan juga sering dibebani dengan tanggung jawab untuk mengetahui cara mendapatkan, dan mengelola, contoh ketergantungan ini, yaitu secara konseptual:

"I need to create/use a Foo and invoke method `GetBar()`"

Sedangkan setelah penerapan DIP, persyaratan dilonggarkan, dan kekhawatiran untuk mendapatkan dan mengelola umur Fooketergantungan telah dihapus:

"I need to invoke something which offers `GetBar()`"

Mengapa menggunakan DIP (dan DI)?

Decoupling dependensi antara kelas-kelas dengan cara ini memungkinkan substitusi yang mudah dari kelas-kelas dependensi ini dengan implementasi lain yang juga memenuhi prasyarat dari abstraksi (misalnya ketergantungan dapat diubah dengan implementasi lain dari antarmuka yang sama). Selain itu, yang lain telah disebutkan, mungkin yang alasan yang paling umum untuk kelas decouple melalui DIP adalah untuk memungkinkan kelas mengkonsumsi untuk diuji dalam isolasi, karena ini dependensi yang sama sekarang dapat mematikan dan / atau mengejek.

Salah satu konsekuensi dari DI adalah manajemen umur instance objek dependensi tidak lagi dikendalikan oleh kelas konsumsi, karena objek dependensi kini diteruskan ke kelas konsumsi (melalui konstruktor atau injeksi setter).

Ini dapat dilihat dengan berbagai cara:

  • Jika kontrol umur pakai dari ketergantungan oleh kelas konsumsi perlu dipertahankan, kontrol dapat didirikan kembali dengan menyuntikkan pabrik (abstrak) untuk membuat instance kelas ketergantungan, ke dalam kelas konsumen. Konsumen akan dapat memperoleh mesin virtual melalui Createpada pabrik sesuai kebutuhan, dan membuang mesin virtual tersebut setelah selesai.
  • Atau, kontrol rentang waktu kejadian dependensi dapat dilepaskan ke wadah IoC (lebih lanjut tentang ini di bawah).

Kapan harus menggunakan DI?

  • Di mana ada kemungkinan akan perlu menggantikan ketergantungan untuk implementasi yang setara,
  • Kapan pun Anda perlu menguji unit metode dalam isolasi dependensinya,
  • Di mana ketidakpastian rentang usia ketergantungan dapat menjamin eksperimen (mis. Hei, MyDepClassapakah thread aman - bagaimana jika kita menjadikannya tunggal dan menyuntikkan contoh yang sama ke semua konsumen?)

Contoh

Berikut ini adalah implementasi C # yang sederhana. Diberikan kelas Konsumsi di bawah ini:

public class MyLogger
{
   public void LogRecord(string somethingToLog)
   {
      Console.WriteLine("{0:HH:mm:ss} - {1}", DateTime.Now, somethingToLog);
   }
}

Meskipun tampaknya tidak berbahaya, ia memiliki dua staticdependensi pada dua kelas lain, System.DateTimedan System.Console, yang tidak hanya membatasi opsi keluaran logging (masuk ke konsol tidak akan bernilai jika tidak ada yang menonton), tetapi lebih buruk lagi, sulit untuk secara otomatis menguji mengingat ketergantungan pada jam sistem non-deterministik.

Namun kita dapat menerapkan DIPke kelas ini, dengan mengabstraksi keprihatinan timestamping sebagai ketergantungan, dan MyLoggerhanya menyambung ke antarmuka sederhana:

public interface IClock
{
    DateTime Now { get; }
}

Kami juga dapat melonggarkan ketergantungan pada Consoleabstraksi, seperti a TextWriter. Dependency Injection biasanya diimplementasikan sebagai constructorinjeksi (meneruskan abstraksi ke dependensi sebagai parameter ke konstruktor dari kelas konsumsi) atau Setter Injection(melewati ketergantungan melalui setXyz()setter atau .Net Properti dengan yang {set;}ditentukan). Injeksi Konstruktor lebih disukai, karena ini menjamin kelas akan berada dalam keadaan yang benar setelah konstruksi, dan memungkinkan bidang dependensi internal ditandai sebagai readonly(C #) atau final(Jawa). Jadi menggunakan injeksi konstruktor pada contoh di atas, ini memberi kita:

public class MyLogger : ILogger // Others will depend on our logger.
{
    private readonly TextWriter _output;
    private readonly IClock _clock;

    // Dependencies are injected through the constructor
    public MyLogger(TextWriter stream, IClock clock)
    {
        _output = stream;
        _clock = clock;
    }

    public void LogRecord(string somethingToLog)
    {
        // We can now use our dependencies through the abstraction 
        // and without knowledge of the lifespans of the dependencies
        _output.Write("{0:yyyy-MM-dd HH:mm:ss} - {1}", _clock.Now, somethingToLog);
    }
}

(Beton Clockperlu disediakan, yang tentu saja dapat dikembalikan DateTime.Now, dan dua dependensi perlu disediakan oleh wadah IoC melalui injeksi konstruktor)

Unit Test otomatis dapat dibangun, yang secara definitif membuktikan bahwa logger kami berfungsi dengan benar, karena kami sekarang memiliki kendali atas dependensi - waktu, dan kami dapat memata-matai hasil tertulis:

[Test]
public void LoggingMustRecordAllInformationAndStampTheTime()
{
    // Arrange
    var mockClock = new Mock<IClock>();
    mockClock.Setup(c => c.Now).Returns(new DateTime(2015, 4, 11, 12, 31, 45));
    var fakeConsole = new StringWriter();

    // Act
    new MyLogger(fakeConsole, mockClock.Object)
        .LogRecord("Foo");

    // Assert
    Assert.AreEqual("2015-04-11 12:31:45 - Foo", fakeConsole.ToString());
}

Langkah selanjutnya

Injeksi ketergantungan selalu terkait dengan wadah Inversion of Control (IoC) , untuk menyuntikkan (menyediakan) contoh ketergantungan beton, dan untuk mengelola contoh umur pakai. Selama proses konfigurasi / bootstrap, IoCwadah memungkinkan yang berikut ini untuk didefinisikan:

  • pemetaan antara setiap abstraksi dan implementasi konkret yang dikonfigurasi (mis. "setiap kali konsumen meminta IBar, kembalikan ConcreteBarcontoh" )
  • kebijakan dapat diatur untuk manajemen masa pakai masing-masing ketergantungan, misalnya untuk membuat objek baru untuk setiap instance konsumen, untuk berbagi contoh ketergantungan tunggal di semua konsumen, untuk berbagi contoh ketergantungan yang sama hanya di seluruh thread yang sama, dll.
  • Di .Net, wadah IoC mengetahui protokol seperti IDisposabledan akan mengambil tanggung jawab Disposingdependensi sejalan dengan manajemen masa pakai yang dikonfigurasi.

Biasanya, begitu wadah IoC telah dikonfigurasi / bootstrap, mereka beroperasi dengan mulus di latar belakang yang memungkinkan koder untuk fokus pada kode yang ada daripada khawatir tentang ketergantungan.

Kunci kode DI-friendly adalah untuk menghindari kopling statis kelas, dan tidak menggunakan yang baru () untuk pembuatan Dependensi

Seperti contoh di atas, decoupling of dependency memang memerlukan beberapa upaya desain, dan bagi pengembang, ada perubahan paradigma yang diperlukan untuk menghentikan kebiasaan newketergantungan secara langsung, dan sebaliknya mempercayai wadah untuk mengelola dependensi.

Tetapi manfaatnya banyak, terutama dalam kemampuan untuk menguji kelas minat Anda secara menyeluruh.

Catatan : Pembuatan / pemetaan / proyeksi (via new ..()) POCO / POJO / Serialisasi DTO / Grafik Entitas / Proyeksi JSON anonim dkk - yaitu kelas atau catatan "Hanya data" - digunakan atau dikembalikan dari metode tidak dianggap sebagai Dependensi (dalam UML sense) dan tidak tunduk pada DI. Menggunakan newuntuk memproyeksikan ini baik-baik saja.

StuartLC
sumber
1
Masalahnya adalah DIP! = DI. DIP adalah tentang memisahkan abstraksi dari implementasi: A. Modul tingkat tinggi tidak harus bergantung pada modul tingkat rendah. Keduanya harus bergantung pada abstraksi. B. Abstraksi tidak harus tergantung pada detail. Rinciannya harus bergantung pada abstraksi. DI adalah cara untuk memisahkan pembuatan objek dari penggunaan objek.
Ricardo Rivaldo
Ya, perbedaannya dengan jelas dinyatakan dalam paragraf 2 saya, "DI salah satu implementasi DIP yang mungkin" , dalam paradigma SOLID Paman Bob. Saya juga sudah menjelaskan hal ini di posting sebelumnya.
StuartLC
25

Inti dari Dependency Injection (DI) adalah menjaga kode sumber aplikasi tetap bersih dan stabil :

  • bersihkan kode inisialisasi dependensi
  • stabil terlepas dari ketergantungan yang digunakan

Secara praktis, setiap pola desain memisahkan masalah untuk membuat perubahan di masa depan memengaruhi file minimum.

Domain spesifik DI adalah pendelegasian konfigurasi dependensi dan inisialisasi.

Contoh: DI dengan skrip shell

Jika Anda sesekali bekerja di luar Jawa, ingat bagaimana sourcesering digunakan dalam banyak bahasa skrip (Shell, Tcl, dll., Atau bahkan importdalam Python disalahgunakan untuk tujuan ini).

Pertimbangkan dependent.shskrip sederhana :

#!/bin/sh
# Dependent
touch         "one.txt" "two.txt"
archive_files "one.txt" "two.txt"

Skrip tergantung: skrip tidak akan berhasil dijalankan dengan sendirinya ( archive_filestidak ditentukan).

Anda mendefinisikan archive_filesdalam archive_files_zip.shskrip implementasi (menggunakan zipdalam kasus ini):

#!/bin/sh
# Dependency
function archive_files {
    zip files.zip "$@"
}

Alih-alih sourcemenjalankan skrip implementasi di dependen, Anda menggunakan injector.sh"wadah" yang membungkus kedua "komponen":

#!/bin/sh 
# Injector
source ./archive_files_zip.sh
source ./dependent.sh

The archive_files ketergantungan baru saja disuntikkan ke dalam tergantung skrip.

Anda bisa menyuntikkan ketergantungan yang mengimplementasikan archive_filesmenggunakan taratau xz.

Contoh: menghapus DI

Jika dependent.shskrip menggunakan dependensi secara langsung, pendekatan akan disebut dependensi lookup (yang berlawanan dengan injeksi dependensi ):

#!/bin/sh
# Dependent

# dependency look-up
source ./archive_files_zip.sh

touch         "one.txt" "two.txt"
archive_files "one.txt" "two.txt"

Sekarang masalahnya adalah "komponen" yang tergantung harus melakukan inisialisasi sendiri.

Kode sumber "komponen" tidak bersih atau stabil karena setiap perubahan inisialisasi dependensi memerlukan rilis baru untuk file kode sumber "komponen" juga.

Kata-kata terakhir

DI tidak begitu ditekankan dan dipopulerkan seperti dalam kerangka kerja Jawa.

Tapi ini adalah pendekatan umum untuk membagi kekhawatiran:

  • pengembangan aplikasi ( siklus rilis kode sumber tunggal )
  • penyebaran aplikasi ( beberapa lingkungan target dengan siklus hidup mandiri)

Menggunakan konfigurasi saja dengan pencarian dependensi tidak membantu karena jumlah parameter konfigurasi dapat berubah per dependensi (mis. Tipe otentikasi baru) serta jumlah tipe dependensi yang didukung (mis. Tipe database baru).

uvsmtid
sumber
Saya akan menambahkan kemampuan untuk menyelesaikan kelas tertentu (pengujian) tanpa harus menyelesaikan dependensinya, sebagai tujuan untuk DI.
David
22

Semua jawaban di atas baik, tujuan saya adalah untuk menjelaskan konsep dengan cara yang sederhana sehingga siapa pun tanpa pengetahuan pemrograman juga dapat memahami konsep

Injeksi ketergantungan adalah salah satu pola desain yang membantu kita menciptakan sistem yang kompleks dengan cara yang lebih sederhana.

Kita dapat melihat beragam penerapan pola ini dalam kehidupan kita sehari-hari. Beberapa contohnya adalah Tape recorder, VCD, CD Drive dll.

Reel-to-reel tape recorder portabel, pertengahan abad ke-20.

Gambar di atas adalah gambar dari tape recorder portabel Reel-to-reel, pertengahan abad ke-20. Sumber .

Tujuan utama dari mesin perekam adalah untuk merekam atau memutar suara.

Saat mendesain sistem, diperlukan gulungan untuk merekam atau memutar suara atau musik. Ada dua kemungkinan untuk merancang sistem ini

  1. kita dapat menempatkan gulungan di dalam mesin
  2. kami dapat menyediakan kait untuk gulungan di mana ia dapat ditempatkan.

Jika kita menggunakan yang pertama, kita perlu membuka mesin untuk mengubah gulungan. jika kita memilih yang kedua, yaitu memasang hook untuk reel, kita mendapatkan keuntungan tambahan dari memainkan musik apa pun dengan mengubah reel. dan juga mengurangi fungsi hanya untuk memainkan apapun dalam reel.

Seperti injeksi dependensi yang bijaksana adalah proses mengeksternalisasi dependensi untuk fokus hanya pada fungsionalitas spesifik komponen sehingga komponen independen dapat digabungkan bersama untuk membentuk sistem yang kompleks.

Manfaat utama yang kami raih dengan menggunakan injeksi ketergantungan.

  • Kohesi tinggi dan kopling longgar.
  • Mengalirkan ketergantungan dan hanya melihat pada tanggung jawab.
  • Menjadikan sesuatu sebagai komponen dan bergabung membentuk sistem besar dengan kemampuan tinggi.
  • Ini membantu untuk mengembangkan komponen berkualitas tinggi karena mereka dikembangkan secara independen mereka diuji dengan baik.
  • Ini membantu untuk mengganti komponen dengan yang lain jika ada yang gagal.

Sekarang suatu hari konsep ini membentuk dasar dari kerangka kerja yang terkenal di dunia pemrograman. Spring Angular dll adalah kerangka kerja perangkat lunak terkenal yang dibangun di atas konsep ini

Dependency injection adalah pola yang digunakan untuk membuat instance objek yang diandalkan objek lain tanpa mengetahui pada waktu kompilasi kelas mana yang akan digunakan untuk menyediakan fungsionalitas itu atau sekadar cara menyuntikkan properti ke objek yang disebut dependensi injeksi.

Contoh untuk injeksi Ketergantungan

Sebelumnya kami menulis kode seperti ini

Public MyClass{
 DependentClass dependentObject
 /*
  At somewhere in our code we need to instantiate 
  the object with new operator  inorder to use it or perform some method.
  */ 
  dependentObject= new DependentClass();
  dependentObject.someMethod();
}

Dengan injeksi Dependency, injector dependensi akan melepas instantiation untuk kita

Public MyClass{
 /* Dependency injector will instantiate object*/
 DependentClass dependentObject

 /*
  At somewhere in our code we perform some method. 
  The process of  instantiation will be handled by the dependency injector
 */ 

  dependentObject.someMethod();
}

Anda juga bisa membaca

Perbedaan antara Pembalikan Kontrol & Ketergantungan Injeksi

samuelj90
sumber
17

Apa itu Injeksi Ketergantungan?

Dependency Injection (DI) artinya memisahkan dua benda yang saling bergantung. Katakanlah objek A bergantung pada Obyek B sehingga idenya adalah untuk memisahkan objek ini dari satu sama lain. Kita tidak perlu membuat hard code objek menggunakan kata kunci baru melainkan berbagi dependensi ke objek pada saat runtime meskipun waktu kompilasi. Jika kita membicarakannya

Cara Kerja Dependency Injection di Spring:

Kita tidak perlu melakukan hard code pada objek menggunakan kata kunci baru melainkan mendefinisikan ketergantungan kacang pada file konfigurasi. Wadah pegas akan bertanggung jawab untuk menghubungkan semua.

Inversion of Control (IOC)

IOC adalah konsep umum dan dapat diekspresikan dengan berbagai cara dan Dependency Injection adalah salah satu contoh nyata IOC.

Dua jenis Injeksi Ketergantungan:

  1. Injeksi Konstruktor
  2. Setter Injection

1. Injeksi ketergantungan berbasis konstruktor:

DI berbasis konstruktor dicapai ketika wadah memanggil konstruktor kelas dengan sejumlah argumen, masing-masing mewakili ketergantungan pada kelas lain.

public class Triangle {

private String type;

public String getType(){
    return type;
 }

public Triangle(String type){   //constructor injection
    this.type=type;
 }
}
<bean id=triangle" class ="com.test.dependencyInjection.Triangle">
        <constructor-arg value="20"/>
  </bean>

2. Injeksi ketergantungan setter-based:

DI berbasis setter dilakukan oleh kontainer yang memanggil metode setter pada kacang Anda setelah memanggil konstruktor tanpa argumen atau metode pabrik statis tanpa argumen untuk membuat instance kacang Anda.

public class Triangle{

 private String type;

 public String getType(){
    return type;
  }
 public void setType(String type){          //setter injection
    this.type = type;
  }
 }

<!-- setter injection -->
 <bean id="triangle" class="com.test.dependencyInjection.Triangle">
        <property name="type" value="equivialteral"/>

CATATAN: Ini adalah aturan praktis yang baik untuk menggunakan argumen konstruktor untuk dependensi wajib dan seter untuk dependensi opsional. Perhatikan bahwa jika kita menggunakan anotasi berdasarkan @ annotasi yang dibutuhkan pada setter dapat digunakan untuk menjadikan setter sebagai dependensi yang diperlukan.

Harleen
sumber
15

Analogi terbaik yang dapat saya pikirkan adalah ahli bedah dan asistennya di ruang operasi, di mana ahli bedah adalah orang utama dan asistennya yang menyediakan berbagai komponen bedah ketika ia membutuhkannya sehingga ahli bedah dapat berkonsentrasi pada satu hal yang ia lakukan terbaik (operasi). Tanpa asisten ahli bedah harus mendapatkan komponen sendiri setiap kali dia membutuhkannya.

Singkatnya, DI adalah teknik untuk menghilangkan tanggung jawab tambahan umum (beban) pada komponen untuk mengambil komponen dependen, dengan menyediakannya.

DI membawa Anda lebih dekat ke prinsip Tanggung Jawab Tunggal (SR), seperti surgeon who can concentrate on surgery.

Kapan harus menggunakan DI: Saya akan merekomendasikan menggunakan DI di hampir semua proyek produksi (kecil / besar), terutama di lingkungan bisnis yang selalu berubah :)

Mengapa: Karena Anda ingin kode Anda mudah diuji, dapat dipermainkan dll sehingga Anda dapat dengan cepat menguji perubahan Anda dan mendorongnya ke pasar. Selain itu mengapa Anda tidak ketika Anda memiliki banyak alat / kerangka kerja gratis yang mengagumkan untuk mendukung Anda dalam perjalanan Anda ke basis kode di mana Anda memiliki kontrol lebih.

Anwar Husain
sumber
@ WindRider Terima kasih. Saya sangat setuju. Kehidupan manusia dan tubuh manusia adalah contoh luar biasa dari keunggulan desain .. tulang belakang adalah contoh yang sangat baik dari ESB:) ...
Anwar Husain
15

Contoh, kami memiliki 2 kelas Clientdan Service. Clientakan menggunakanService

public class Service {
    public void doSomeThingInService() {
        // ...
    }
}

Tanpa Injeksi Ketergantungan

Cara 1)

public class Client {
    public void doSomeThingInClient() {
        Service service = new Service();
        service.doSomeThingInService();
    }
}

Jalan 2)

public class Client {
    Service service = new Service();
    public void doSomeThingInClient() {
        service.doSomeThingInService();
    }
}

Jalan 3)

public class Client {
    Service service;
    public Client() {
        service = new Service();
    }
    public void doSomeThingInClient() {
        service.doSomeThingInService();
    }
}

1) 2) 3) Menggunakan

Client client = new Client();
client.doSomeThingInService();

Keuntungan

  • Sederhana

Kekurangan

  • Sulit untuk Clientkelas tes
  • Ketika kita mengubah Servicekonstruktor, kita perlu mengubah kode di semua tempat membuat Serviceobjek

Gunakan Injeksi Ketergantungan

Cara 1) Injeksi konstruktor

public class Client {
    Service service;

    Client(Service service) {
        this.service = service;
    }

    // Example Client has 2 dependency 
    // Client(Service service, IDatabas database) {
    //    this.service = service;
    //    this.database = database;
    // }

    public void doSomeThingInClient() {
        service.doSomeThingInService();
    }
}

Menggunakan

Client client = new Client(new Service());
// Client client = new Client(new Service(), new SqliteDatabase());
client.doSomeThingInClient();

Cara 2) Setter injection

public class Client {
    Service service;

    public void setService(Service service) {
        this.service = service;
    }

    public void doSomeThingInClient() {
        service.doSomeThingInService();
    }
}

Menggunakan

Client client = new Client();
client.setService(new Service());
client.doSomeThingInClient();

Cara 3) Injeksi antarmuka

Periksa https://en.wikipedia.org/wiki/Dependency_injection

===

Sekarang, kode ini sudah mengikuti Dependency Injectiondan lebih mudah untuk Clientkelas uji .
Namun, kami masih menggunakan new Service()banyak waktu dan itu tidak baik ketika mengganti Servicekonstruktor. Untuk mencegahnya, kita dapat menggunakan injektor DI seperti
1) Manual sederhanaInjector

public class Injector {
    public static Service provideService(){
        return new Service();
    }

    public static IDatabase provideDatatBase(){
        return new SqliteDatabase();
    }
    public static ObjectA provideObjectA(){
        return new ObjectA(provideService(...));
    }
}

Menggunakan

Service service = Injector.provideService();

2) Gunakan perpustakaan: Untuk Android dagger2

Keuntungan

  • Buat tes lebih mudah
  • Ketika Anda mengubah Service, Anda hanya perlu mengubahnya di kelas Injector
  • Jika Anda menggunakan gunakan Constructor Injection, ketika Anda melihat konstruktor Client, Anda akan melihat berapa banyak ketergantungan Clientkelas

Kekurangan

  • Jika Anda menggunakan use Constructor Injection, Serviceobjek dibuat saat Clientdibuat, kadang-kadang kita menggunakan fungsi di Clientkelas tanpa menggunakan Servicesehingga dibuat Serviceterbuang sia-sia

Definisi Injeksi Ketergantungan

https://en.wikipedia.org/wiki/Dependency_injection

Ketergantungan adalah objek yang dapat digunakan ( Service)
Suntikan adalah melewati ketergantungan ( Service) ke objek dependen ( Client) yang akan menggunakannya

Phan Van Linh
sumber
13

Ini berarti bahwa objek hanya memiliki dependensi sebanyak yang diperlukan untuk melakukan pekerjaannya dan dependensi harus sedikit. Selain itu, dependensi objek harus berada pada antarmuka dan bukan pada objek "konkret", jika memungkinkan. (Objek konkret adalah objek apa pun yang dibuat dengan kata kunci baru.) Kopling longgar mempromosikan penggunaan kembali yang lebih besar, pemeliharaan lebih mudah, dan memungkinkan Anda untuk dengan mudah menyediakan objek "tiruan" di tempat layanan mahal.

"Injeksi Ketergantungan" (DI) juga dikenal sebagai "Inversion of Control" (IoC), dapat digunakan sebagai teknik untuk mendorong sambungan longgar ini.

Ada dua pendekatan utama untuk mengimplementasikan DI:

  1. Injeksi konstruktor
  2. Injeksi setter

Injeksi konstruktor

Ini adalah teknik meneruskan ketergantungan objek kepada konstruktornya.

Perhatikan bahwa konstruktor menerima antarmuka dan bukan objek konkret. Juga, perhatikan bahwa pengecualian dilemparkan jika parameter orderDao adalah nol. Ini menekankan pentingnya menerima ketergantungan yang valid. Injeksi Konstruktor adalah, menurut pendapat saya, mekanisme yang disukai untuk memberikan objek ketergantungannya. Jelas bagi pengembang sambil memanggil objek yang dependensi perlu diberikan ke objek "Orang" untuk eksekusi yang tepat.

Setter Injection

Tetapi perhatikan contoh berikut ... Misalkan Anda memiliki kelas dengan sepuluh metode yang tidak memiliki dependensi, tetapi Anda menambahkan metode baru yang memang memiliki ketergantungan pada IDAO. Anda bisa mengubah konstruktor untuk menggunakan Injeksi Konstruktor, tetapi ini mungkin memaksa Anda untuk mengubah semua panggilan konstruktor di semua tempat. Atau, Anda bisa menambahkan konstruktor baru yang menggunakan dependensi, tetapi kemudian bagaimana pengembang dengan mudah tahu kapan harus menggunakan satu konstruktor di atas yang lain. Akhirnya, jika ketergantungan sangat mahal untuk dibuat, mengapa itu harus dibuat dan diteruskan ke konstruktor padahal mungkin hanya jarang digunakan? "Setter Injection" adalah teknik DI lainnya yang dapat digunakan dalam situasi seperti ini.

Setter Injection tidak memaksa ketergantungan untuk diteruskan ke konstruktor. Alih-alih, dependensi diatur ke properti publik yang diekspos oleh objek yang membutuhkan. Seperti yang tersirat sebelumnya, motivator utama untuk melakukan ini meliputi:

  1. Mendukung injeksi ketergantungan tanpa harus memodifikasi konstruktor kelas warisan.
  2. Mengizinkan sumber daya atau layanan mahal dibuat selambat mungkin dan hanya jika diperlukan.

Berikut adalah contoh bagaimana kode di atas akan terlihat seperti:

public class Person {
    public Person() {}

    public IDAO Address {
        set { addressdao = value; }
        get {
            if (addressdao == null)
              throw new MemberAccessException("addressdao" +
                             " has not been initialized");
            return addressdao;
        }
    }

    public Address GetAddress() {
       // ... code that uses the addressdao object
       // to fetch address details from the datasource ...
    }

    // Should not be called directly;
    // use the public property instead
    private IDAO addressdao;
Piyush Deshpande
sumber
3
Saya pikir paragraf pertama Anda menyimpang dari pertanyaan, dan sama sekali tidak definisi DI (yaitu, Anda mencoba mendefinisikan SOLID, bukan DI). Secara teknis, bahkan jika Anda memiliki 100 dependensi, Anda masih bisa menggunakan injeksi dependensi. Demikian pula, dimungkinkan untuk menyuntikkan dependensi beton - masih injeksi ketergantungan.
Jay Sullivan
10

Saya pikir karena semua orang telah menulis untuk DI, izinkan saya mengajukan beberapa pertanyaan ..

  1. Ketika Anda memiliki konfigurasi DI di mana semua implementasi aktual (bukan interface) yang akan disuntikkan ke kelas (untuk layanan misalnya ke controller) mengapa itu bukan semacam hard-coding?
  2. Bagaimana jika saya ingin mengubah objek saat runtime? Sebagai contoh, konfigurasi saya sudah mengatakan ketika saya instantiate MyController, menyuntikkan FileLogger sebagai ILogger. Tapi saya mungkin ingin menyuntikkan DatabaseLogger.
  3. Setiap kali saya ingin mengubah objek apa yang dibutuhkan AClass saya, sekarang saya perlu melihat ke dua tempat - Kelas itu sendiri dan file konfigurasi. Bagaimana hal itu membuat hidup lebih mudah?
  4. Jika Aproperty of AClass tidak disuntikkan, apakah lebih sulit untuk mengejeknya?
  5. Kembali ke pertanyaan pertama. Jika menggunakan objek baru () buruk, mengapa kita menyuntikkan implementasi dan bukan antarmuka? Saya pikir banyak dari Anda mengatakan kami sebenarnya menyuntikkan antarmuka tetapi konfigurasi membuat Anda menentukan implementasi antarmuka itu .. tidak saat runtime .. itu hardcoded selama waktu kompilasi.

Ini didasarkan pada jawaban @Adam N yang diposting.

Mengapa PersonService tidak perlu lagi khawatir tentang GroupMembershipService? Anda baru saja menyebutkan bahwa GroupMembership memiliki banyak hal (objek / properti) yang tergantung padanya. Jika GMService diperlukan di PService, Anda akan memilikinya sebagai properti. Anda dapat mengejek itu terlepas dari apakah Anda menyuntikkannya atau tidak. Satu-satunya waktu saya ingin disuntikkan adalah jika GMService memiliki kelas anak yang lebih spesifik, yang Anda tidak akan tahu sampai runtime. Maka Anda ingin menyuntikkan subclass. Atau jika Anda ingin menggunakannya sebagai singleton atau prototipe. Sejujurnya, file konfigurasi memiliki semua hardcoded sejauh apa subkelas untuk tipe (antarmuka) yang akan disuntikkan selama waktu kompilasi.

EDIT

Komentar bagus oleh Jose Maria Arranz di DI

DI meningkatkan kohesi dengan menghilangkan kebutuhan untuk menentukan arah ketergantungan dan menulis kode lem.

Salah. Arah dependensi adalah dalam bentuk XML atau sebagai anotasi, dependensi Anda ditulis sebagai kode XML dan anotasi. XML dan anotasi ADALAH kode sumber.

DI mengurangi kopling dengan membuat semua komponen Anda menjadi modular (dapat diganti) dan memiliki antarmuka yang saling ditentukan dengan baik.

Salah. Anda tidak perlu kerangka DI untuk membangun kode modular berdasarkan antarmuka.

Tentang yang dapat diganti: dengan arsip .properties dan Class.forName yang sangat sederhana, Anda dapat menentukan kelas mana yang dapat diubah. Jika kelas APAPUN kode Anda dapat diubah, Java bukan untuk Anda, gunakan bahasa scripting. Omong-omong: anotasi tidak dapat diubah tanpa kompilasi ulang.

Menurut pendapat saya ada satu-satunya alasan untuk kerangka kerja DI: pengurangan pelat ketel. Dengan sistem pabrik yang dilakukan dengan baik, Anda dapat melakukan hal yang sama, lebih terkontrol, dan lebih dapat diprediksi sebagai kerangka kerja DI pilihan Anda, kerangka kerja DI menjanjikan pengurangan kode (XML dan anotasi juga merupakan kode sumber). Masalahnya adalah pengurangan pelat ketel ini hanya nyata dalam kasus yang sangat sangat sederhana (satu instance-per kelas dan serupa), kadang-kadang di dunia nyata memilih objek layanan yang sesuai tidak semudah memetakan kelas ke objek tunggal.

Chookoo
sumber
8

Jawaban populer tidak membantu, karena mereka mendefinisikan injeksi ketergantungan dengan cara yang tidak berguna. Mari kita sepakati bahwa dengan "ketergantungan" yang kita maksud adalah beberapa objek lain yang sudah ada sebelumnya yang dibutuhkan oleh objek X kita. Tapi kami tidak mengatakan kami melakukan "injeksi ketergantungan" ketika kami mengatakannya

$foo = Foo->new($bar);

Kami hanya memanggil parameter yang lewat ke konstruktor. Kami telah melakukan itu secara teratur sejak konstruktor ditemukan.

"Injeksi ketergantungan" dianggap sebagai jenis "inversi kontrol", yang berarti bahwa beberapa logika dikeluarkan dari pemanggil. Itu tidak terjadi ketika pemanggil melewati parameter, jadi jika itu DI, DI tidak akan menyiratkan inversi kontrol.

DI berarti ada tingkat menengah antara pemanggil dan konstruktor yang mengelola dependensi. Makefile adalah contoh sederhana injeksi ketergantungan. "Penelepon" adalah orang yang mengetik "make bar" pada baris perintah, dan "konstruktor" adalah kompiler. Makefile menetapkan bahwa bilah bergantung pada foo, dan bilah

gcc -c foo.cpp; gcc -c bar.cpp

sebelum melakukan a

gcc foo.o bar.o -o bar

Orang yang mengetik "make bar" tidak perlu tahu bahwa bar tergantung pada foo. Ketergantungan disuntikkan antara "make bar" dan gcc.

Tujuan utama dari tingkat menengah bukan hanya untuk meneruskan dependensi ke konstruktor, tetapi untuk membuat daftar semua dependensi hanya dalam satu tempat , dan untuk menyembunyikannya dari coder (bukan untuk membuat coder menyediakannya).

Biasanya tingkat menengah menyediakan pabrik untuk objek yang dibangun, yang harus memberikan peran yang harus dipenuhi oleh setiap jenis objek yang diminta. Itu karena dengan memiliki tingkat menengah yang menyembunyikan detail konstruksi, Anda sudah dikenai penalti abstraksi yang dikenakan oleh pabrik, jadi sebaiknya Anda menggunakan pabrik.

Phil Goetz
sumber
8

Dependency Injection berarti cara (sebenarnya cara apa pun ) untuk satu bagian kode (misalnya kelas) untuk memiliki akses ke dependensi (bagian lain dari kode, misalnya kelas lain, tergantung pada) dengan cara modular tanpa harus dikodekan (jadi mereka dapat berubah atau diganti secara bebas, atau bahkan dimuat pada waktu lain, sesuai kebutuhan)

(dan ps, ya itu telah menjadi nama 25 $ terlalu-hyped untuk konsep, agak sederhana) , .25sen saya

Nikos M.
sumber
8

Saya tahu sudah ada banyak jawaban, tetapi saya menemukan ini sangat membantu: http://tutorials.jenkov.com/dependency-injection/index.html

Tidak Ada Ketergantungan:

public class MyDao {

  protected DataSource dataSource = new DataSourceImpl(
    "driver", "url", "user", "password");

  //data access methods...
  public Person readPerson(int primaryKey) {...}     
}

Ketergantungan:

public class MyDao {

  protected DataSource dataSource = null;

  public MyDao(String driver, String url, String user, String password) {
    this.dataSource = new DataSourceImpl(driver, url, user, password);
  }

  //data access methods...
  public Person readPerson(int primaryKey) {...}
}

Perhatikan bagaimana DataSourceImplinstantiasi dipindahkan ke konstruktor. Konstruktor mengambil empat parameter yang merupakan empat nilai yang dibutuhkan oleh DataSourceImpl. Meskipun MyDaokelas masih bergantung pada empat nilai ini, itu tidak lagi memenuhi dependensi itu sendiri. Mereka disediakan oleh kelas apa pun yang membuat MyDaoinstance.

Ali Issa
sumber
1
Tidakkah DI melewati Anda dengan antarmuka DataSourceImp Anda sudah dibangun?
PmanAce
6

Injeksi ketergantungan adalah salah satu solusi yang memungkinkan untuk apa yang secara umum dapat disebut persyaratan "Ketergantungan Kebingungan". Dependency Obfuscation adalah metode untuk menghilangkan sifat 'jelas' dari proses penyediaan ketergantungan pada kelas yang membutuhkannya dan oleh karena itu mengaburkan, dalam beberapa cara, penyediaan ketergantungan tersebut kepada kelas tersebut. Ini belum tentu hal yang buruk. Pada kenyataannya, dengan mengaburkan cara dimana ketergantungan diberikan kepada kelas maka sesuatu di luar kelas bertanggung jawab untuk menciptakan ketergantungan yang berarti, dalam berbagai skenario, implementasi ketergantungan yang berbeda dapat dipasok ke kelas tanpa membuat perubahan apa pun. ke kelas. Ini bagus untuk beralih antara mode produksi dan pengujian (mis., Menggunakan ketergantungan layanan 'mock').

Sayangnya bagian yang buruk adalah bahwa beberapa orang berasumsi bahwa Anda memerlukan kerangka kerja khusus untuk melakukan kebingungan dependensi dan bahwa Anda entah bagaimana merupakan programmer yang 'lebih rendah' ​​jika Anda memilih untuk tidak menggunakan kerangka kerja tertentu untuk melakukannya. Mitos lain yang sangat mengganggu, diyakini oleh banyak orang, adalah bahwa injeksi ketergantungan adalah satu-satunya cara untuk mencapai kebingungan ketergantungan. Ini terbukti dan historis dan jelas 100% salah, tetapi Anda akan kesulitan meyakinkan beberapa orang bahwa ada alternatif untuk injeksi ketergantungan untuk persyaratan kebingungan ketergantungan Anda.

Pemrogram telah memahami persyaratan kebingungan ketergantungan selama bertahun-tahun dan banyak solusi alternatif telah berkembang sebelum dan setelah injeksi ketergantungan dikandung. Ada pola Pabrik tetapi ada juga banyak opsi menggunakan ThreadLocal di mana tidak diperlukan injeksi ke instance tertentu - ketergantungan secara efektif disuntikkan ke thread yang memiliki manfaat membuat objek tersedia (melalui metode pengambil statis yang mudah) untuk setiapkelas yang membutuhkannya tanpa harus menambahkan anotasi ke kelas yang membutuhkannya dan mengatur 'lem' XML yang rumit untuk mewujudkannya. Ketika dependensi Anda diperlukan untuk kegigihan (JPA / JDO atau apa pun) itu memungkinkan Anda untuk mencapai 'kegigihan tranaparen' jauh lebih mudah dan dengan model domain dan kelas model bisnis yang dibuat murni dari POJO (yaitu tidak ada kerangka kerja spesifik / terkunci dalam anotasi).

Volksman
sumber
5

Sebelum pergi ke deskripsi teknis, visualisasikan terlebih dahulu dengan contoh nyata karena Anda akan menemukan banyak hal teknis untuk belajar injeksi ketergantungan tetapi waktu maksimum orang-orang seperti saya tidak bisa mendapatkan konsep inti itu.

Pada gambar pertama, Asumsikan bahwa Anda memiliki pabrik mobil dengan banyak persatuan. Mobil sebenarnya dibangun di unit perakitan tetapi membutuhkan mesin , kursi , dan roda . Jadi unit perakitan tergantung pada semua unit ini dan mereka adalah ketergantungan pabrik.

Anda dapat merasakan bahwa sekarang ini terlalu rumit untuk mempertahankan semua tugas di pabrik ini karena seiring dengan tugas utama (Merakit mobil dalam unit Perakitan) Anda harus juga fokus pada unit lain . Sekarang sangat mahal untuk dirawat dan bangunan pabrik sangat besar sehingga dibutuhkan uang ekstra untuk disewa.

Sekarang, lihat gambar kedua. Jika Anda menemukan beberapa perusahaan penyedia yang akan memberi Anda roda , kursi , dan mesin lebih murah daripada biaya produksi sendiri, maka sekarang Anda tidak perlu membuatnya di pabrik Anda. Anda dapat menyewa gedung yang lebih kecil sekarang hanya untuk unit perakitan Anda yang akan mengurangi tugas perawatan Anda dan mengurangi biaya sewa tambahan Anda. Sekarang Anda juga dapat fokus hanya pada tugas utama Anda (Perakitan mobil).

Sekarang kita dapat mengatakan bahwa semua dependensi untuk merakit mobil disuntikkan di pabrik dari penyedia . Ini adalah contoh dari Dependency Injection (DI) kehidupan nyata .

Sekarang dalam kata teknis, injeksi ketergantungan adalah teknik di mana satu objek (atau metode statis) memasok dependensi objek lain. Jadi, mentransfer tugas untuk membuat objek ke orang lain dan langsung menggunakan dependensi disebut dependensi injeksi.

Ini akan membantu Anda sekarang untuk belajar DI dengan beberapa kata techy. Ini akan menunjukkan kapan harus menggunakan DI dan kapan tidak .

Semua dalam satu pabrik mobil.

Pabrik mobil sederhana

Gk Mohammad Emon
sumber
1
jawaban paling jelas dari 40 ish. Contoh dan gambar kehidupan nyata. +1. Seharusnya jawaban yang diterima.
Marche Remi
4

dari Book Apress.Spring.Persistence.with.Hibernate.Oct.2010

Tujuan dari injeksi ketergantungan adalah untuk memisahkan pekerjaan penyelesaian komponen perangkat lunak eksternal dari logika bisnis aplikasi Anda. Tanpa injeksi ketergantungan, detail tentang bagaimana komponen mengakses layanan yang diperlukan dapat menjadi kacau dengan kode komponen. Ini tidak hanya meningkatkan potensi kesalahan, menambah kode mengasapi, dan memperbesar kompleksitas perawatan; itu menyatukan komponen bersama-sama lebih dekat, sehingga sulit untuk memodifikasi dependensi saat refactoring atau pengujian.

BERGUIGA Mohamed Amine
sumber
4

Dependency Injection (DI) adalah salah satu dari Pola Desain, yang menggunakan fitur dasar OOP - hubungan dalam satu objek dengan objek lain. Sementara warisan mewarisi satu objek untuk melakukan objek lain yang lebih kompleks dan spesifik, hubungan atau asosiasi hanya membuat pointer ke objek lain dari satu objek menggunakan atribut. Kekuatan DI dalam kombinasi dengan fitur-fitur OOP lainnya seperti antarmuka dan kode penyembunyian. Misalkan, kami memiliki pelanggan (pelanggan) di perpustakaan, yang dapat meminjam hanya satu buku untuk kesederhanaan.

Antarmuka buku:

package com.deepam.hidden;

public interface BookInterface {

public BookInterface setHeight(int height);
public BookInterface setPages(int pages);   
public int getHeight();
public int getPages();  

public String toString();
}

Selanjutnya kita dapat memiliki banyak jenis buku; salah satu jenisnya adalah fiksi:

package com.deepam.hidden;

public class FictionBook implements BookInterface {
int height = 0; // height in cm
int pages = 0; // number of pages

/** constructor */
public FictionBook() {
    // TODO Auto-generated constructor stub
}

@Override
public FictionBook setHeight(int height) {
  this.height = height;
  return this;
}

@Override
public FictionBook setPages(int pages) {
  this.pages = pages;
  return this;      
}

@Override
public int getHeight() {
    // TODO Auto-generated method stub
    return height;
}

@Override
public int getPages() {
    // TODO Auto-generated method stub
    return pages;
}

@Override
public String toString(){
    return ("height: " + height + ", " + "pages: " + pages);
}
}

Sekarang pelanggan dapat memiliki hubungan dengan buku:

package com.deepam.hidden;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Subscriber {
BookInterface book;

/** constructor*/
public Subscriber() {
    // TODO Auto-generated constructor stub
}

// injection I
public void setBook(BookInterface book) {
    this.book = book;
}

// injection II
public BookInterface setBook(String bookName) {
    try {
        Class<?> cl = Class.forName(bookName);
        Constructor<?> constructor = cl.getConstructor(); // use it for parameters in constructor
        BookInterface book = (BookInterface) constructor.newInstance();
        //book = (BookInterface) Class.forName(bookName).newInstance();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
    return book;
}

public BookInterface getBook() {
  return book;
}

public static void main(String[] args) {

}

}

Ketiga kelas dapat disembunyikan untuk implementasi itu sendiri. Sekarang kita dapat menggunakan kode ini untuk DI:

package com.deepam.implement;

import com.deepam.hidden.Subscriber;
import com.deepam.hidden.FictionBook;

public class CallHiddenImplBook {

public CallHiddenImplBook() {
    // TODO Auto-generated constructor stub
}

public void doIt() {
    Subscriber ab = new Subscriber();

    // injection I
    FictionBook bookI = new FictionBook();
    bookI.setHeight(30); // cm
    bookI.setPages(250);
    ab.setBook(bookI); // inject
    System.out.println("injection I " + ab.getBook().toString());

    // injection II
    FictionBook bookII = ((FictionBook) ab.setBook("com.deepam.hidden.FictionBook")).setHeight(5).setPages(108); // inject and set
    System.out.println("injection II " + ab.getBook().toString());      
}

public static void main(String[] args) {
    CallHiddenImplBook kh = new CallHiddenImplBook();
    kh.doIt();
}
}

Ada banyak cara berbeda cara menggunakan injeksi ketergantungan. Dimungkinkan untuk menggabungkannya dengan Singleton, dll., Tetapi pada dasarnya itu hanya asosiasi yang diwujudkan dengan membuat atribut tipe objek di dalam objek lain. Kegunaannya hanya dan hanya dalam fitur, kode itu, yang harus kita tulis berulang kali selalu disiapkan dan dilakukan untuk kita maju. Inilah sebabnya mengapa DI begitu terikat erat dengan Inversion of Control (IoC) yang berarti, bahwa program kami melewati kontrol modul berjalan lain, yang melakukan suntikan kacang ke kode kami. (Setiap objek, yang dapat disuntikkan dapat ditandatangani atau dianggap sebagai Bean.) Misalnya di Spring itu dilakukan dengan membuat dan menginisialisasi ApplicationContextwadah, yang ini bekerja untuk kita. Kami hanya dalam kode kami membuat Konteks dan memohon inisialisasi kacang. Pada saat itu injeksi telah dilakukan secara otomatis.

hariprasad
sumber
4

Ketergantungan Injeksi untuk anak usia 5 tahun.

Ketika Anda pergi dan mengambil sendiri barang-barang dari lemari es, Anda dapat menyebabkan masalah. Anda mungkin membiarkan pintu terbuka, Anda mungkin mendapatkan sesuatu yang Ibu atau Ayah tidak ingin Anda miliki. Anda mungkin bahkan mencari sesuatu yang bahkan tidak kita miliki atau yang telah kedaluwarsa.

Yang harus Anda lakukan adalah menyatakan suatu kebutuhan, "Saya perlu minum dengan makan siang," dan kemudian kami akan memastikan Anda memiliki sesuatu ketika Anda duduk untuk makan.

Nithin Prasad
sumber
1
Ini jelas jawaban orangtua. ;)
Marche Remi
4

Dari Christoffer Noring, buku Pablo Deeleman "Learning Angular - Second Edition":

"Ketika aplikasi kita tumbuh dan berkembang, masing-masing entitas kode kita secara internal akan membutuhkan instance dari objek lain , yang lebih dikenal sebagai dependensi dalam dunia rekayasa perangkat lunak. Tindakan meneruskan dependensi tersebut kepada klien dependen dikenal sebagai injeksi , dan itu juga memerlukan partisipasi dari entitas kode lain, bernama injector . injector akan bertanggung jawab untuk instantiating dan bootstrap yang diperlukan dependensi yangsehingga mereka siap digunakan sejak saat mereka berhasil disuntikkan ke klien. Ini sangat penting karena klien tidak tahu apa-apa tentang instantiate dependensinya sendiri dan hanya mengetahui antarmuka yang mereka implementasikan untuk menggunakannya. "

Dari: Anton Moiseev. buku "Pengembangan Sudut dengan Naskah, Edisi Kedua.":

"Singkatnya, DI membantu Anda menulis kode dengan cara yang digabungkan secara longgar dan membuat kode Anda lebih dapat diuji dan digunakan kembali ."

HS Progr
sumber
3

Sederhananya, dependensi injection (DI) adalah cara untuk menghilangkan dependensi atau ikatan erat antara objek yang berbeda. Dependency Injection memberikan perilaku kohesif untuk setiap objek.

DI adalah implementasi dari kepala IOC Spring yang mengatakan "Jangan panggil kami, kami akan menghubungi Anda". Menggunakan dependensi injeksi programmer tidak perlu membuat objek menggunakan kata kunci baru.

Objek pernah dimuat dalam wadah Spring dan kemudian kita menggunakannya kembali kapan pun kita membutuhkannya dengan mengambil objek-objek dari wadah Spring menggunakan metode getBean (String beanName).

Waqas Ahmed
sumber
3

Ketergantungan injeksi adalah jantung dari konsep yang terkait dengan Kerangka Kerja Pegas. Sementara menciptakan kerangka kerja dari setiap pegas proyek dapat melakukan peran vital, dan di sini injeksi ketergantungan datang dengan kendi.

Sebenarnya, Misalkan di java Anda membuat dua kelas yang berbeda sebagai kelas A dan kelas B, dan apa pun fungsi yang tersedia di kelas B yang ingin Anda gunakan di kelas A, Jadi pada saat itu ketergantungan injeksi dapat digunakan. di mana Anda dapat membuat objek dari satu kelas di kelas lain, dengan cara yang sama Anda bisa menyuntikkan seluruh kelas di kelas lain untuk membuatnya dapat diakses. dengan cara ini ketergantungan dapat diatasi.

INJEKSI TERGANTUNG ADALAH SEDERHANA MENGGOSOK DUA KELAS DAN PADA SAAT YANG SAMA MENJAGA MEREKA TERPISAH.

mohit sarsar
sumber