Ketergantungan Injeksi vs Pola Pabrik


498

Sebagian besar contoh dikutip untuk penggunaan Injeksi Ketergantungan, kita dapat memecahkan menggunakan pola pabrik juga. Sepertinya ketika datang ke penggunaan / desain perbedaan antara injeksi ketergantungan dan pabrik kabur atau tipis.

Pernah seseorang mengatakan kepada saya bahwa cara Anda menggunakannya membuat perbedaan!

Saya pernah menggunakan StructureMap sebagai wadah DI untuk menyelesaikan masalah, kemudian saya mendesain ulang untuk bekerja dengan pabrik sederhana dan menghapus referensi ke StructureMap.

Adakah yang bisa memberitahu saya apa perbedaan antara mereka dan di mana menggunakan apa, apa praktik terbaik di sini?


22
Tidak bisakah kedua pendekatan ini saling melengkapi: menggunakan Injeksi Ketergantungan untuk menyuntikkan kelas pabrik?
Richard Ev

20
Akan sangat menyenangkan jika pertanyaan ini memiliki jawaban dengan beberapa kode di dalamnya! Saya masih tidak melihat bagaimana DI akan bermanfaat / berbeda dari menggunakan pabrik untuk pembuatan? Anda hanya perlu mengganti satu baris di kelas pabrik untuk mengubah objek / implementasi yang dibuat?
gideon

2
@gideon tidak akan memaksa Anda untuk mengkompilasi aplikasi Anda, atau setidaknya modul yang berisi kelas pabrik?
asam lisergik

1
@liortal ya itu benar. Melakukan studi panjang pada DI sejak komentar itu dan sekarang saya mengerti DI mengambil metode pabrik selangkah lebih maju.
gideon

1
Lihatlah jawaban yang bagus ini: stackoverflow.com/questions/4985455/… - dia mengucapkannya dengan sangat baik dan memberikan contoh kode.
Luis Perez

Jawaban:


294

Saat menggunakan pabrik kode Anda sebenarnya masih bertanggung jawab untuk membuat objek. Dengan DI Anda mengalihkan tanggung jawab itu ke kelas lain atau kerangka kerja, yang terpisah dari kode Anda.


172
Pola DI tidak membutuhkan kerangka kerja apa pun. Anda dapat melakukan DI dengan secara manual menulis pabrik yang melakukan DI. Kerangka kerja DI hanya membuatnya lebih mudah.
Esko Luontola

28
@Perpetualcoder - Terima kasih @Esko - Jangan terjebak pada kerangka kata yang berarti beberapa perpustakaan pihak ke-3 yang canggih.
willcodejavaforfood

4
+1 @willcode terima kasih! Jadi, Anda harus mengubah file config / xml sebagai gantinya. Saya melihat. Tautan wiki en.wikipedia.org/wiki/… mendefinisikan pola pabrik sebagaiManually-Injected Dependency
gideon

5
Saya tidak mendapatkan keuntungan dari mengubah 1 baris XML vs mengubah 1 baris kode. Bisakah Anda menguraikan?
Rafael Eyng

1
Ulangi jawaban OP dengan mengganti "DI" dengan "pabrik", masih masuk akal.
Edson Medina

219

Saya menyarankan untuk menjaga konsepnya tetap sederhana dan sederhana. Ketergantungan Injeksi lebih dari pola arsitektur untuk komponen perangkat lunak kopling longgar. Pola pabrik hanyalah salah satu cara untuk memisahkan tanggung jawab membuat objek dari kelas lain ke entitas lain. Pola pabrik dapat disebut sebagai alat untuk mengimplementasikan DI. Ketergantungan injeksi dapat diimplementasikan dalam banyak cara seperti DI menggunakan konstruktor, menggunakan pemetaan file xml dll.


4
Itu benar bahwa Pola Pabrik adalah salah satu cara menerapkan Ketergantungan Injeksi. Manfaat lain menggunakan Ketergantungan Injeksi terhadap Pola Pabrik adalah bahwa Kerangka DI akan memberi Anda fleksibilitas cara mendaftarkan abstraksi Anda terhadap jenis beton Anda. Seperti Kode sebagai Konfigurasi, XML atau Konfigurasi Otomatis. Fleksibilitas itu akan memberi Anda mengelola seumur hidup objek Anda atau memutuskan bagaimana dan kapan mendaftarkan antarmuka Anda.
Teoman shipahi

1
Pola pabrik menawarkan abstraksi tingkat yang lebih tinggi daripada DI. Pabrik dapat menawarkan opsi konfigurasi seperti DI, tetapi juga dapat memilih untuk menyembunyikan semua detail konfigurasi tersebut, sehingga pabrik dapat memutuskan untuk beralih ke implementasi yang sama sekali berbeda tanpa sepengetahuan klien. DI sendiri tidak mengizinkan ini. DI mengharuskan klien untuk menentukan perubahan yang diinginkannya.
neuron

1
Jawaban bagus. Banyak yang bingung dengan pertanyaan itu: "Pola apa yang harus saya pilih?" Faktanya, pola desain hanyalah cara untuk memecahkan masalah pada situasi yang tepat. Jika Anda tidak tahu pola desain apa yang harus Anda gunakan, atau "Di mana saya harus menerapkan pola?" maka Anda tidak membutuhkannya saat ini.
Benyi

2
Saya pikir lebih tepat untuk mengatakan Factory Pattern adalah alat untuk mengimplementasikan IoC (bukan DI). Harap dicatat bahwa DI adalah bentuk
IoC

185

Injeksi Ketergantungan

Alih-alih membuat contoh bagian-bagian itu sendiri, mobil meminta bagian-bagian yang perlu berfungsi.

class Car
{
    private Engine engine;
    private SteeringWheel wheel;
    private Tires tires;

    public Car(Engine engine, SteeringWheel wheel, Tires tires)
    {
        this.engine = engine;
        this.wheel = wheel;
        this.tires = tires;
    }
}

Pabrik

Letakkan potongan-potongan untuk membuat objek yang lengkap dan menyembunyikan jenis beton dari penelepon.

static class CarFactory
{
    public ICar BuildCar()
    {
        Engine engine = new Engine();
        SteeringWheel steeringWheel = new SteeringWheel();
        Tires tires = new Tires();
        ICar car = new RaceCar(engine, steeringWheel, tires);
        return car;
    }   
}

Hasil

Seperti yang Anda lihat, Pabrik dan DI saling melengkapi.

static void Main()
{
     ICar car = CarFactory.BuildCar();
     // use car
}

Apakah Anda ingat goldilocks dan tiga beruang? Nah, injeksi ketergantungan semacam itu. Berikut adalah tiga cara untuk melakukan hal yang sama.

void RaceCar() // example #1
{
    ICar car = CarFactory.BuildCar();
    car.Race();
}

void RaceCar(ICarFactory carFactory) // example #2
{
    ICar car = carFactory.BuildCar();
    car.Race();
}

void RaceCar(ICar car) // example #3
{
    car.Race();
}

Contoh # 1 - Ini adalah yang terburuk karena sepenuhnya menyembunyikan ketergantungan. Jika Anda melihat metode ini sebagai kotak hitam, Anda tidak akan tahu itu membutuhkan mobil.

Contoh # 2 - Ini sedikit lebih baik karena sekarang kita tahu kita membutuhkan mobil karena kita melewati pabrik mobil. Tapi kali ini kami melewati terlalu banyak karena semua metode yang sebenarnya dibutuhkan adalah mobil. Kami melewati sebuah pabrik hanya untuk membangun mobil ketika mobil bisa dibangun di luar metode dan lewat.

Contoh # 3 - ini sangat ideal karena metode meminta persis apa yang dibutuhkan. Tidak terlalu banyak atau terlalu sedikit. Saya tidak perlu menulis MockCarFactory hanya untuk membuat MockCars, saya bisa langsung lulus mock. Ini langsung dan antarmuka tidak berbohong.

Google Tech Talk oleh Misko Hevery ini luar biasa dan merupakan dasar dari mana saya berasal. http://www.youtube.com/watch?v=XcT4yYu_TTs


1
Pola Pabrik disuntikkan sebagai DI.
Mangesh Pimpalkar

7
@ PhilGoetz Apa yang Anda gambarkan terdengar lebih seperti pola Service Locator. Mereka memiliki tujuan yang sama, yaitu bertujuan untuk memisahkan layanan dari konsumen mereka. Namun, ada banyak kelemahan pada pola Layanan Locator. Terutama, menyembunyikan ketergantungan bukanlah hal yang baik. Konsumen masih perlu mendapatkan ketergantungannya, tetapi alih-alih mendefinisikan antarmuka yang jelas, mereka dilewatkan secara 'diam-diam' dan mengandalkan negara global. Dalam contoh tersebut, konsumen tidak tahu tentang pabrik, ia hanya menanyakan apa yang dibutuhkannya dan tidak perlu khawatir tentang bagaimana kebutuhan itu dibangun.
Despertar

1
@MatthewWhited Sebagian besar keputusan desain memiliki trade off. Dengan DI, Anda mendapatkan fleksibilitas, transparansi, dan sistem yang lebih dapat diuji, tetapi dengan mengorbankan nyali Anda. Banyak orang menganggap ini sebagai trade off yang dapat diterima. Ini bukan untuk mengatakan bahwa DI selalu merupakan solusi terbaik dan pertanyaan ini bukan tentang itu. Contoh ini dimaksudkan untuk menunjukkan perbedaan antara DI dan pola pabrik dengan menunjukkan beberapa kegunaan baik dan buruk dari masing-masing.
Despertar

3
Ini bukan pola DI, ini hanya implementasi IOC. DI menggunakan ServiceLocator untuk menentukan ketergantungan yang tepat dan menyuntikkannya ke dalam konstruktor selama pembuatan objek, kode Anda hanya memisahkan pembuatan objek dari ruang lingkup kelas Anda.
Diego Mendes

3
@DiegoMendes Apa yang Anda gambarkan adalah kerangka kerja yang mengotomatiskan DI. ServiceLocator seperti yang Anda sebut itu melakukan DI untuk Anda. Apa yang saya perlihatkan adalah pola itu sendiri yang tidak memerlukan kerangka kerja mewah. Lihat stackoverflow.com/a/140655/1160036 , atau lihat en.wikipedia.org/wiki/… : "[daftar kerangka kerja] mendukung injeksi dependensi tetapi tidak diharuskan untuk melakukan injeksi dependensi". Juga, "Suntikan adalah berlalunya ketergantungan ke objek tergantung". Anda terlalu rumit konsep sederhana yang indah.
Despertar

50

Alasan Ketergantungan Injeksi (DI) dan Pola Pabrik serupa adalah karena mereka adalah dua implementasi dari Inversion of Control (IoC) yang merupakan arsitektur perangkat lunak. Sederhananya mereka adalah dua solusi untuk masalah yang sama.

Jadi untuk menjawab pertanyaan, perbedaan utama antara pola Pabrik dan DI adalah bagaimana referensi objek diperoleh. Dengan injeksi dependensi sesuai namanya, referensi disuntikkan atau diberikan ke kode Anda. Dengan pola Pabrik kode Anda harus meminta referensi sehingga kode Anda mengambil objek. Kedua implementasi menghapus atau memisahkan hubungan antara kode dan kelas yang mendasari atau jenis referensi objek yang digunakan oleh kode.

Perlu dicatat bahwa pola Pabrik (atau pola Pabrik Abstrak yang merupakan pabrik yang mengembalikan pabrik baru yang mengembalikan referensi objek) dapat ditulis untuk secara dinamis memilih atau menautkan ke jenis atau kelas objek yang diminta pada waktu berjalan. Ini membuat mereka sangat mirip (bahkan lebih daripada DI) dengan pola Service Locator yang merupakan implementasi lain dari IoC.

Pola desain Pabrik sudah cukup lama (dalam hal Perangkat Lunak) dan telah ada untuk sementara waktu. Karena popularitas terkini dari pola arsitektur IoC, ia mengalami kebangkitan.

Saya kira ketika datang ke pola desain IoC: injector menjadi injecting, locator menjadi locating dan pabrik-pabrik telah di refactored.


3
Ini adalah jawaban terbaik ... jawaban lain tidak menyebutkan IOC atau tidak mengakui bahwa DI adalah bentuk IOC.
Hooman Bahreini

Terima kasih, ketika saya pertama kali belajar IOC saya hampir berteriak bahwa ini hanyalah bentuk lain dari pola pabrik, ternyata mereka benar-benar mirip satu sama lain
Harvey Lin

40

Ada masalah yang mudah diselesaikan dengan injeksi ketergantungan yang tidak begitu mudah diselesaikan dengan serangkaian pabrik.

Beberapa perbedaan antara, di satu sisi, inversi kontrol dan injeksi ketergantungan (IOC / DI), dan, di sisi lain, pelacak layanan atau rangkaian pabrik (pabrik), adalah:

IOC / DI adalah ekosistem lengkap dari objek dan layanan domain dalam dan dari dirinya sendiri. Ini mengatur segalanya untuk Anda dengan cara yang Anda tentukan. Anda objek dan layanan domain dibangun oleh wadah, dan tidak membangun diri mereka sendiri: mereka karena itu tidak memiliki apapun dependensi pada wadah atau pabrik apapun. IOC / DI memungkinkan tingkat konfigurasi yang sangat tinggi, dengan semua konfigurasi di satu tempat (konstruksi wadah) di lapisan paling atas dari aplikasi Anda (GUI, Web front-end).

Abstrak pabrik menghilangkan sebagian konstruksi objek dan layanan domain Anda. Tetapi objek dan layanan domain masih bertanggung jawab untuk mencari tahu bagaimana membangun diri mereka sendiri dan bagaimana mendapatkan semua hal yang mereka andalkan. Semua dependensi "aktif" ini memfilter semua lapisan aplikasi Anda. Tidak ada satu tempat untuk pergi untuk mengkonfigurasi semuanya.


26

Salah satu kelemahan DI adalah tidak dapat menginisialisasi objek dengan logika. Misalnya, ketika saya perlu membuat karakter yang memiliki nama dan usia acak, DI bukan pilihan atas pola pabrik. Dengan pabrik, kita dapat dengan mudah merangkum algoritma acak dari pembuatan objek, yang mendukung salah satu pola desain yang disebut "Enkapsulasi apa yang bervariasi".


22

Manajemen siklus hidup adalah salah satu tanggung jawab yang diemban oleh kontainer ketergantungan selain dari instantiasi dan injeksi. Fakta bahwa wadah kadang-kadang menyimpan referensi ke komponen setelah instantiation adalah alasan itu disebut "wadah", dan bukan pabrik. Wadah injeksi ketergantungan biasanya hanya menyimpan referensi ke objek yang diperlukan untuk mengatur siklus hidup, atau yang digunakan kembali untuk injeksi di masa depan, seperti lajang atau bobot terbang. Ketika dikonfigurasikan untuk membuat instance baru dari beberapa komponen untuk setiap panggilan ke kontainer, kontainer biasanya hanya lupa tentang objek yang dibuat.

Dari: http://tutorials.jenkov.com/dependency-injection/dependency-injection-containers.html


15

Saya percaya DI adalah jenis lapisan abstraksi pada pabrik, tetapi mereka juga memberikan manfaat di luar abstraksi. Pabrik sejati tahu bagaimana membuat instantiate satu tipe dan mengkonfigurasinya. Lapisan DI yang baik memberikan kemampuan, melalui konfigurasi, untuk membuat instance dan mengkonfigurasi banyak jenis.

Jelas, untuk proyek dengan beberapa tipe sederhana yang memerlukan logika bisnis yang relatif stabil dalam konstruksi mereka, pola pabrik mudah dipahami, diimplementasikan, dan bekerja dengan baik.

OTOH, jika Anda memiliki proyek yang berisi banyak jenis yang implementasinya Anda harapkan akan sering berubah, DI memberi Anda fleksibilitas melalui konfigurasinya untuk melakukan ini saat runtime tanpa harus mengkompilasi ulang pabrik Anda.


14

Teori

Ada dua poin penting untuk dipertimbangkan:

  1. Siapa yang menciptakan objek

    • [Pabrik]: Anda harus menulis BAGAIMANA objek harus dibuat. Anda memiliki kelas Pabrik terpisah yang berisi logika pembuatan.
    • [Injeksi Ketergantungan]: Dalam kasus praktis dilakukan oleh kerangka kerja eksternal (misalnya di Jawa yang akan menjadi pegas / ejb / guice). Injeksi terjadi secara "ajaib" tanpa penciptaan objek baru secara eksplisit
  2. Jenis objek apa yang ia kelola:

    • [Pabrik]: Biasanya bertanggung jawab atas pembuatan objek stateful
    • [Suntikan Ketergantungan] Lebih cenderung membuat objek stateless

Contoh praktis bagaimana menggunakan injeksi pabrik dan ketergantungan dalam satu proyek

  1. Apa yang ingin kita bangun

Modul aplikasi untuk membuat pesanan yang berisi banyak entri yang disebut orderline.

  1. Arsitektur

Mari kita asumsikan kita ingin membuat arsitektur layer berikut:

masukkan deskripsi gambar di sini

Objek domain dapat berupa objek yang disimpan di dalam basis data. Repositori (DAO) membantu dengan pengambilan objek dari database. Layanan menyediakan API ke modul lain. Memungkinkan operasi pada ordermodul

  1. Lapisan Domain dan penggunaan pabrik

Entitas yang akan ada di database adalah Order dan OrderLine. Order dapat memiliki beberapa OrderLines. Hubungan antara Order dan OrderLine

Kini hadir bagian desain yang penting. Haruskah modul di luar yang ini membuat dan mengelola OrderLines sendiri? Tidak. Jalur Pemesanan hanya akan ada bila Anda memiliki Pesanan yang terkait dengannya. Akan lebih baik jika Anda bisa menyembunyikan implementasi internal ke kelas luar.

Tetapi bagaimana cara membuat Pesanan tanpa pengetahuan tentang OrderLines?

Pabrik

Seseorang yang ingin membuat pesanan baru menggunakan OrderFactory (yang akan menyembunyikan detail tentang fakta bagaimana kita membuat Pesanan).

masukkan deskripsi gambar di sini

Begitulah tampilannya di dalam IDE. Kelas di luar domainpaket akan digunakan OrderFactorysebagai pengganti konstruktor di dalamOrder

  1. Dependency Injection Injeksi ketergantungan lebih umum digunakan dengan lapisan stateless seperti repositori dan layanan.

OrderRepository dan OrderService dikelola oleh kerangka kerja injeksi ketergantungan. Repositori bertanggung jawab untuk mengelola operasi CRUD pada basis data. Layanan menyuntikkan Repositori dan menggunakannya untuk menyimpan / menemukan kelas domain yang benar.

masukkan deskripsi gambar di sini


Bisakah Anda menjelaskan ini? [Factory]: Usually responsible for creation of stateful objects [Dependency Injections] More likely to create stateless objectsSaya tidak mengerti mengapa
Maksim Dmitriev

2
Objek stateful cenderung berada di lapisan aplikasi domain di mana Anda memetakan data Anda ke database Anda biasanya tidak menggunakan injeksi ketergantungan di sana. Pabrik sering digunakan untuk membuat AgregatRoot dari pohon benda yang rumit
Marcin Szymczak

12

Saya tahu pertanyaan ini sudah lama tetapi saya ingin menambahkan lima sen saya,

Saya pikir injeksi ketergantungan (DI) dalam banyak hal seperti Pola Pabrik yang dapat dikonfigurasi (FP), dan dalam hal apa pun yang dapat Anda lakukan dengan DI, Anda akan dapat melakukannya dengan pabrik tersebut.

Sebenarnya, jika Anda menggunakan pegas misalnya, Anda memiliki opsi untuk sumber daya autowiring (DI) atau melakukan sesuatu seperti ini:

MyBean mb = ctx.getBean("myBean");

Dan kemudian gunakan contoh 'mb' untuk melakukan apa saja. Bukankah itu panggilan ke pabrik yang akan mengembalikan Anda sebuah contoh ??

Satu-satunya perbedaan nyata yang saya perhatikan antara sebagian besar contoh FP adalah bahwa Anda dapat mengonfigurasi apa "myBean" yang ada di xml atau di kelas lain, dan kerangka kerja akan berfungsi sebagai pabrik, tetapi selain itu adalah hal yang sama, dan Anda dapat memiliki Pabrik yang pasti membaca file konfigurasi atau mendapatkan implementasi sesuai kebutuhan.

Dan jika Anda meminta pendapat saya (dan saya tahu Anda tidak), saya percaya bahwa DI melakukan hal yang sama tetapi hanya menambah kompleksitas pada pengembangan, mengapa?

baik, untuk satu hal, agar Anda tahu apa implementasi yang digunakan untuk kacang yang Anda autowire dengan DI, Anda harus pergi ke konfigurasi itu sendiri.

tapi ... bagaimana dengan janji itu bahwa Anda tidak perlu tahu implementasi objek yang Anda gunakan? pfft! serius? ketika Anda menggunakan pendekatan seperti ini ... bukankah Anda sama dengan yang menulis implementasinya ?? dan bahkan jika tidak, bukankah Anda hampir setiap saat melihat bagaimana implementasi melakukan apa yang seharusnya dilakukan ??

dan untuk satu hal terakhir, tidak masalah seberapa banyak kerangka kerja DI menjanjikan Anda bahwa Anda akan membangun hal-hal yang terpisah darinya, tanpa ada ketergantungan pada kelas mereka, jika Anda menggunakan kerangka kerja Anda membangun semuanya dengan cepat, jika Anda harus mengubah pendekatan atau kerangka kerja itu tidak akan menjadi tugas yang mudah ... PERNAH! ... tetapi, karena Anda membangun segala sesuatu di sekitar kerangka kerja itu alih-alih mengkhawatirkan solusi terbaik untuk bisnis Anda, maka Anda akan menghadapi masalah besar saat melakukan itu.

Bahkan, satu-satunya aplikasi bisnis nyata untuk pendekatan FP atau DI yang dapat saya lihat adalah jika Anda perlu mengubah implementasi yang digunakan saat runtime , tetapi setidaknya kerangka kerja yang saya tahu tidak memungkinkan Anda untuk melakukan itu, Anda harus meninggalkan semuanya sempurna dalam konfigurasi pada waktu pengembangan dan jika Anda memerlukannya, gunakan pendekatan lain.

Jadi, jika saya memiliki kelas yang berkinerja berbeda dalam dua lingkup dalam aplikasi yang sama (katakanlah, dua perusahaan holding) saya harus mengkonfigurasi kerangka kerja untuk membuat dua kacang yang berbeda, dan menyesuaikan kode saya untuk menggunakan masing-masing. Bukankah itu sama dengan jika saya hanya akan menulis sesuatu seperti ini:

MyBean mb = MyBeanForEntreprise1(); //In the classes of the first enterprise
MyBean mb = MyBeanForEntreprise2(); //In the classes of the second enterprise

sama seperti ini:

@Autowired MyBean mbForEnterprise1; //In the classes of the first enterprise
@Autowired MyBean mbForEnterprise2; //In the classes of the second enterprise

Dan ini:

MyBean mb = (MyBean)MyFactory.get("myBeanForEntreprise1"); //In the classes of the first enterprise
MyBean mb = (MyBean)MyFactory.get("myBeanForEntreprise2"); //In the classes of the second enterprise

Bagaimanapun Anda harus mengubah sesuatu dalam aplikasi Anda, apakah kelas atau file konfigurasi, tetapi Anda harus melakukannya dan memindahkannya.

Bukankah lebih baik melakukan sesuatu seperti ini:

MyBean mb = (MyBean)MyFactory.get("mb"); 

Dan dengan cara itu, Anda mengatur kode pabrik untuk mendapatkan implementasi yang tepat saat runtime tergantung pada perusahaan pengguna yang dicatat ?? Sekarang itu akan sangat membantu. Anda bisa menambahkan tabung baru dengan kelas-kelas baru dan mengatur aturan bahkan mungkin saat runtime (atau menambahkan file konfigurasi baru jika Anda membiarkan opsi ini terbuka), tidak ada perubahan pada kelas yang ada. Ini akan menjadi pabrik yang Dinamis!

bukankah itu lebih bermanfaat daripada harus menulis dua konfigurasi untuk setiap perusahaan, dan mungkin bahkan memiliki dua aplikasi yang berbeda untuk masing-masing ??

Anda dapat memberi tahu saya, saya tidak perlu melakukan pergantian saat runtime, jadi saya mengkonfigurasi aplikasi, dan jika saya mewarisi kelas atau menggunakan implementasi lain, saya hanya mengubah konfigurasi dan memindahkan. Ok, itu juga bisa dilakukan dengan pabrik. Dan jujur, berapa kali Anda melakukan ini? mungkin hanya ketika Anda memiliki aplikasi yang akan digunakan di tempat lain di perusahaan Anda, dan Anda akan meneruskan kode ke tim lain, dan mereka akan melakukan hal-hal seperti ini. Tapi hei, itu juga bisa dilakukan dengan pabrik, dan akan lebih baik dengan pabrik yang dinamis !!

Pokoknya, bagian komentar jika terbuka bagimu untuk membunuhku.


3
Terlalu banyak pengembang berpikir bahwa kerangka Ketergantungan Injeksi dibuat untuk membawa sesuatu yang baru. Seperti yang Anda jelaskan, pabrik-pabrik tradisional (paling sering pabrik abstrak) dapat memainkan peran yang sama dari inversi ketergantungan. Inversi vs Injeksi? Bagi saya, satu-satunya "manfaat" dari kerangka kerja Dependency Injection adalah bahwa kami belum mengubah / mengkompilasi ulang kode (karena paling sering dapat dikonfigurasi dengan XML seperti Spring) ketika dependensi ditambahkan / diubah. Mengapa menghindari kompilasi ulang? Untuk menghindari beberapa kesalahan manusia yang potensial saat mengubah ketergantungan / pabrik. Tetapi dengan IDE kami yang hebat, refactoring dapat berjalan dengan baik :)
Mik378

6

IOC adalah konsep yang diimplementasikan dengan dua cara. Ketergantungan penciptaan dan injeksi ketergantungan, Pabrik / pabrik Abstrak adalah contoh penciptaan ketergantungan. Ketergantungan injeksi adalah konstruktor, setter, dan antarmuka. Inti dari IOC adalah untuk tidak bergantung pada kelas beton, tetapi mendefinisikan abstrak metode (katakanlah antarmuka / kelas abstrak) dan gunakan abstrak itu untuk memanggil metode kelas beton. Seperti pola Pabrik mengembalikan kelas dasar atau antarmuka. Injeksi ketergantungan serupa menggunakan kelas / antarmuka dasar untuk menetapkan nilai untuk objek.


4

Dengan injeksi dependensi, klien tidak perlu mendapatkan dependensinya sendiri, semuanya dipersiapkan sebelumnya.

Dengan pabrik, seseorang harus memanggil benda-benda itu untuk membawa benda-benda yang dihasilkan ke tempat mereka dibutuhkan.

Perbedaannya sebagian besar terletak pada baris yang satu ini di mana memanggil pabrik dan mengambil objek yang dibangun dilakukan.

Tetapi dengan pabrik Anda harus menulis 1 baris ini di mana-mana Anda memerlukan objek seperti itu. Dengan DI Anda hanya perlu membuat kabel (hubungan antara penggunaan dan objek yang dibuat) sekali dan hanya mengandalkan keberadaan objek sesudahnya di mana-mana. Di sisi lain, DI sering membutuhkan sedikit lebih banyak (berapa banyak tergantung pada kerangka kerja) bekerja di sisi persiapan.


3

Saya memiliki pertanyaan yang sama segera setelah saya membaca tentang DI dan berakhir di pos ini. Jadi akhirnya ini yang saya mengerti tapi tolong perbaiki saya jika saya salah.

"Dahulu kala ada kerajaan kecil dengan badan pemerintahannya sendiri yang mengendalikan dan mengambil keputusan berdasarkan aturan tertulis mereka sendiri. Kemudian membentuk pemerintahan besar yang menghilangkan semua badan pemerintahan kecil yang memiliki satu set aturan (konstitusi) dan dilaksanakan melalui pengadilan"

Badan pemerintahan kerajaan kecil adalah "Pabrik"

Pemerintah besar adalah "Dependency Injector".


1
Jadi, KAPAN seorang codsider yang dulu dimiliki pemerintah kecil menjadi besar? Dengan ukuran apa?
Tahanan ZERO

3

Anda dapat melihat tautan ini untuk perbandingan dua pendekatan (dan lainnya) dalam contoh nyata.

Pada dasarnya, ketika persyaratan berubah, Anda akhirnya memodifikasi lebih banyak kode jika Anda menggunakan pabrik dan bukan DI.

Ini juga berlaku dengan DI manual (yaitu ketika tidak ada kerangka kerja eksternal yang menyediakan dependensi ke objek Anda, tetapi Anda meneruskannya di setiap konstruktor).


3

Sebagian besar jawaban di sini menjelaskan perbedaan konseptual dan detail implementasi keduanya. Namun saya tidak dapat menemukan penjelasan tentang perbedaan dalam aplikasi IMO mana yang paling penting dan OP bertanya. Jadi izinkan saya membuka kembali topik ini ...

Pernah seseorang mengatakan kepada saya bahwa cara Anda menggunakannya membuat perbedaan!

Persis. Dalam 90% kasus, Anda dapat memperoleh referensi objek menggunakan Pabrik atau DI dan biasanya Anda berakhir dengan yang terakhir. Dalam 10% kasus lain menggunakan Factory hanya cara yang benar . Kasus-kasus ini termasuk mendapatkan objek dengan variabel pada parameter runtime. Seperti ini:

IWebClient client = factoryWithCache.GetWebClient(url: "stackoverflow.com",
        useCookies: false, connectionTimeout: 120);

Dalam hal ini, mendapatkan clientdari DI tidak dimungkinkan (atau setidaknya memerlukan beberapa solusi buruk). Jadi sebagai aturan umum untuk mengambil keputusan: jika dependensi dapat diperoleh tanpa parameter perhitungan runtime maka DI lebih disukai, jika tidak gunakan Factory.


2

Saya percaya bahwa DI adalah cara konfigurasi atau instantianting kacang. DI dapat dilakukan dengan berbagai cara seperti konstruktor, setter-pengambil, dll.

Pola pabrik hanyalah cara lain untuk membuat biji kopi. pola ini akan digunakan terutama ketika Anda harus membuat objek menggunakan pola desain pabrik, karena saat menggunakan pola ini Anda tidak mengkonfigurasi properti kacang, hanya instantiate objek.

Periksa tautan ini: Injeksi Ketergantungan


2

Binoj,

Saya tidak berpikir Anda harus memilih satu dari yang lain.

Tindakan memindahkan kelas dependen atau antarmuka ke konstruktor atau setter kelas mengikuti pola DI. Objek yang Anda berikan ke konstruktor atau set dapat diimplementasikan dengan Factory.

Kapan menggunakannya? Gunakan pola atau pola yang ada di ruang kemudi pengembang Anda. Apa yang mereka rasakan paling nyaman dan paling mudah dipahami.


2

Saya percaya, 3 aspek penting mengatur objek dan penggunaannya:
1. Instansiasi (kelas bersama dengan inisialisasi jika ada).
2. Injeksi (dari instance yang dibuat) di mana diperlukan.
3. Manajemen siklus hidup (misalnya dibuat begitu).

Menggunakan pola Factory, aspek pertama (instantiation) dicapai tetapi dua sisanya dipertanyakan. Kelas yang menggunakan instance lain harus melakukan hardcode pada pabrik (alih-alih instance yang dibuat) yang menghambat kemampuan kopling longgar. Apalagi manajemen siklus hidupcontoh menjadi tantangan dalam aplikasi besar di mana pabrik digunakan di banyak tempat (terutama, jika pabrik tidak mengelola siklus hidup contoh itu kembali, itu menjadi jelek).

Sebaliknya, menggunakan DI (pola IoC), ketiganya diabstraksi di luar kode (ke wadah DI) dan kacang yang dikelola tidak memerlukan apa pun tentang kompleksitas ini. Loose Coupling , tujuan arsitektur yang sangat penting dapat dicapai dengan tenang dengan nyaman. Tujuan arsitektur penting lainnya, pemisahan kekhawatiran dapat dicapai jauh lebih baik daripada pabrik.

Sedangkan Pabrik mungkin cocok untuk aplikasi kecil, yang besar akan lebih baik untuk memilih DI daripada pabrik.


1

Pikiran saya:

Dependecy Injection: meneruskan kolaborator sebagai parameter ke konstruktor. Dependency Injection Framework: pabrik generik dan dapat dikonfigurasi untuk membuat objek untuk dilewatkan sebagai parameter ke konstruktor.


1
Ya persis. Hampir semua sebutan Injeksi Ketergantungan (DI) dalam T&J ini menyalahgunakan istilah ini berbeda dengan definisi ini. Dependency Injection Container (DIC) adalah kerangka kerja paling umum yang bertindak sebagai pabrik generik dan dapat dikonfigurasi untuk membuat objek.
CXJ

1

Kerangka Kerja Injeksi adalah implementasi dari Pola Pabrik.

Itu semua tergantung pada kebutuhan Anda. Jika Anda perlu menerapkan pola pabrik dalam suatu aplikasi, kemungkinan besar persyaratan Anda akan dipenuhi oleh salah satu dari banyak implementasi kerangka kerja injeksi di luar sana.

Anda hanya harus meluncurkan solusi Anda sendiri jika persyaratan Anda tidak dapat dipenuhi oleh salah satu kerangka kerja pihak ke-3. Semakin banyak kode yang Anda tulis, semakin banyak kode yang harus Anda pertahankan. Kode adalah liabilitas bukan aset.

Argumen tentang implementasi mana yang harus Anda gunakan tidak sepenting memahami kebutuhan arsitektur aplikasi Anda.


1

Pola Desain Pabrik

Pola desain pabrik ditandai oleh

  • Antarmuka
  • Kelas implementasi
  • Sebuah pabrik

Anda dapat mengamati beberapa hal ketika Anda bertanya pada diri sendiri seperti di bawah ini

  • Kapan pabrik akan membuat objek untuk kelas implementasi - run time atau compile time?
  • Bagaimana jika Anda ingin mengganti implementasi saat dijalankan? - Tidak mungkin

Ini ditangani dengan injeksi Ketergantungan.

Ketergantungan injeksi

Anda dapat memiliki berbagai cara untuk menyuntikkan ketergantungan. Untuk kesederhanaan mari kita pergi dengan Injeksi Antarmuka

Dalam DI, wadah membuat instance yang dibutuhkan, dan "menyuntikkan" mereka ke objek.

Dengan demikian menghilangkan instantiasi statis.

Contoh:

public class MyClass{

  MyInterface find= null;

  //Constructor- During the object instantiation

  public MyClass(MyInterface myInterface ) {

       find = myInterface ;
  }

  public void myMethod(){

       find.doSomething();

  }
}

1

Dari nilai nominal mereka terlihat sama

Dalam istilah yang sangat sederhana, Pola Pabrik, Pola Penciptaan membantu membuat kita objek - "Tentukan antarmuka untuk membuat objek". Jika kita memiliki semacam nilai kunci dari kumpulan objek (mis. Kamus), meneruskan kunci ke Pabrik (saya mengacu pada Pola Pabrik Sederhana) Anda dapat menyelesaikan Jenis. Pekerjaan selesai! Kerangka Injeksi Ketergantungan (seperti Struktur Peta, Ninject, Persatuan ... dll) di sisi lain tampaknya melakukan hal yang sama.

Tapi ... "Jangan menemukan kembali kemudi"

Dari perspektif arsitektur, ini adalah lapisan yang mengikat dan "Jangan menemukan kembali roda".

Untuk aplikasi kelas perusahaan, konsep DI lebih merupakan lapisan arsitektur yang mendefinisikan dependensi. Untuk menyederhanakan ini lebih lanjut, Anda dapat menganggap ini sebagai proyek perpustakaan kelas terpisah, yang tidak menyelesaikan ketergantungan. Aplikasi utama tergantung pada proyek ini di mana Penyelesai ketergantungan merujuk pada implementasi konkret lainnya dan penyelesaian ketergantungan.

Selain untuk "GetType / Buat" dari Pabrik, paling sering kita membutuhkan lebih banyak fitur (kemampuan untuk menggunakan XML untuk menentukan dependensi, mengejek dan pengujian unit dll.). Karena Anda merujuk ke Peta Struktur, lihat daftar fitur Peta Struktur . Ini jelas lebih dari sekedar menyelesaikan Pemetaan objek sederhana. Jangan menemukan kembali roda!

Jika yang Anda miliki adalah palu, semuanya terlihat seperti paku

Bergantung pada kebutuhan Anda dan jenis aplikasi apa yang Anda bangun, Anda harus membuat pilihan. Jika hanya memiliki beberapa proyek (mungkin satu atau dua ..) dan melibatkan beberapa dependensi, Anda dapat memilih pendekatan yang lebih sederhana. Ini seperti menggunakan akses data ADO .Net menggunakan Entity Framework untuk panggilan basis data 1 atau 2 yang sederhana, di mana memperkenalkan EF adalah kerja keras dalam skenario itu.

Tetapi untuk proyek yang lebih besar atau jika proyek Anda semakin besar, saya akan sangat menyarankan untuk memiliki lapisan DI dengan kerangka kerja dan memberikan ruang untuk mengubah kerangka kerja DI yang Anda gunakan (Gunakan Fasad di Aplikasi Utama (Aplikasi Web, Web Api, Desktop ..etc.).


1

Dengan pabrik Anda dapat mengelompokkan antarmuka terkait, Jadi Jika parameter yang dilewati dapat dikelompokkan dalam sebuah pabrik maka itu juga merupakan solusi yang baik untuk constructor overinjectionmelihat kode ini *):

public AddressModelFactory(IAddressAttributeService addressAttributeService,
        IAddressAttributeParser addressAttributeParser,
        ILocalizationService localizationService,
        IStateProvinceService stateProvinceService,
        IAddressAttributeFormatter addressAttributeFormatter)
    {
        this._addressAttributeService = addressAttributeService;
        this._addressAttributeParser = addressAttributeParser;
        this._localizationService = localizationService;
        this._stateProvinceService = stateProvinceService;
        this._addressAttributeFormatter = addressAttributeFormatter;
    }

Lihatlah konstruktor, Anda hanya perlu melewati IAddressModelFactorysana, jadi lebih sedikit parameter *):

 public CustomerController(IAddressModelFactory addressModelFactory,
        ICustomerModelFactory customerModelFactory,
        IAuthenticationService authenticationService,
        DateTimeSettings dateTimeSettings,
        TaxSettings taxSettings,
        ILocalizationService localizationService,
        IWorkContext workContext,
        IStoreContext storeContext,
        ICustomerService customerService,
        ICustomerAttributeParser customerAttributeParser,
        ICustomerAttributeService customerAttributeService,
        IGenericAttributeService genericAttributeService,
        ICustomerRegistrationService customerRegistrationService,
        ITaxService taxService,
        CustomerSettings customerSettings,
        AddressSettings addressSettings,...

Anda melihat dalam CustomerControllerbanyak parameter yang dilewati, Ya Anda bisa melihat ini sebagai constructor overinjectiontetapi ini adalah cara DI bekerja. Dan tidak ada yang salah dengan CustomerController.

*) Kode berasal dari nopCommerce.


1

Secara sederhana, Injeksi Ketergantungan vs metode Pabrik menyiratkan mekanisme push vs pull masing-masing.

Mekanisme tarikan : kelas secara tidak langsung memiliki ketergantungan pada Metode Pabrik yang pada gilirannya memiliki ketergantungan pada kelas beton.

Mekanisme dorong : Komponen root dapat dikonfigurasikan dengan semua komponen dependen di satu lokasi dan dengan demikian mempromosikan pemeliharaan tinggi dan kopling longgar.

Dengan metode Factory, tanggung jawab masih terletak pada kelas (meskipun secara tidak langsung) untuk membuat objek baru di mana dengan injeksi ketergantungan tanggung jawab dialihdayakan (dengan biaya abstraksi yang bocor)


0

Saya pikir ini orthogonal dan dapat digunakan bersama. Izinkan saya menunjukkan kepada Anda sebuah contoh yang baru-baru ini saya temui di tempat kerja:

Kami menggunakan kerangka Spring di Jawa untuk DI. Kelas singleton ( Parent) harus membuat instance objek baru dari kelas lain ( Child), dan mereka memiliki kolaborator kompleks:

@Component
class Parent {
    // ...
    @Autowired
    Parent(Dep1 dep1, Dep2 dep2, ..., DepN depN) {
        this.dep1 = dep1;
        this.dep2 = dep2;
    }

    void method(int p) {
        Child c = new Child(dep1, dep2, ..., depN, p);
        // ...
    }
}

Dalam contoh ini, Parentharus menerima DepXcontoh hanya untuk meneruskannya ke Childkonstruktor. Masalah dengan ini:

  1. Parentmemiliki pengetahuan lebih dari Childyang seharusnya
  2. Parent memiliki lebih banyak kolaborator daripada yang seharusnya
  3. Menambahkan dependensi Childmelibatkan perubahanParent

Ini adalah ketika saya menyadari Factoryakan cocok di sini dengan sempurna:

  1. Itu menyembunyikan semua kecuali parameter sebenarnya dari Childkelas, seperti yang terlihat olehParent
  2. Ini merangkum pengetahuan membuat Child, yang dapat dipusatkan di konfigurasi DI.

Ini adalah Parentkelas yang disederhanakan dan ChildFactorykelas:

@Component
class Parent {
    // ...
    @Autowired
    Parent(ChildFactory childFactory) {
        this.childFactory = childFactory;
    }

    void method(int p) {
        Child c = childFactory.newChild(p);
        // ...
    }
}

@Component
class ChildFactory {
    // ...
    @Autowired
    Parent(Dep1 dep1, Dep2 dep2, ..., DepN depN) {
        this.dep1 = dep1;
        this.dep2 = dep2;
        // ...
        this.depN = depN;
    }

    Child newChild(int p) {
        return new Child(dep1, dep2, ..., depN, p);
    }
}

0

Anda menggunakan injeksi ketergantungan ketika Anda tahu persis jenis objek yang Anda butuhkan pada titik waktu ini. Sementara dalam kasus pola pabrik, Anda hanya mendelegasikan proses membuat objek ke pabrik karena Anda tidak jelas tentang jenis objek yang Anda butuhkan.


-1

Saya menggunakan keduanya untuk membuat strategi Inversion Of Control dengan lebih mudah dibaca untuk pengembang yang perlu mempertahankannya setelah saya.

Saya menggunakan Pabrik untuk membuat objek Layer saya yang berbeda (Bisnis, Akses Data).

ICarBusiness carBusiness = BusinessFactory.CreateCarBusiness();

Pengembang lain akan melihat ini dan ketika membuat objek Business Layer ia terlihat di BusinessFactory dan Intellisense memberi pengembang semua Layers Bisnis yang mungkin untuk dibuat. Tidak harus memainkan permainan, temukan Antarmuka yang ingin saya buat.

Struktur ini sudah menjadi Inversion Of Control. Saya tidak lagi bertanggung jawab untuk membuat objek tertentu. Tetapi Anda masih perlu memastikan Dependency Injection untuk dapat mengubah banyak hal dengan mudah. Membuat Injeksi Ketergantungan kustom Anda sendiri konyol, jadi saya menggunakan Unity. Di dalam CreateCarBusiness () saya meminta Unity untuk Menyelesaikan kelas mana yang menjadi bagian dari ini dan itu seumur hidup.

Jadi struktur kode Injeksi Ketergantungan Pabrik saya adalah:

public static class BusinessFactory
{
    public static ICarBusiness CreateCarBusiness()
    {
       return Container.Resolve<ICarBusiness>();
    }
}

Sekarang saya mendapat manfaat dari keduanya. Kode saya juga lebih mudah dibaca oleh pengembang lain dibandingkan dengan cakupan objek yang saya gunakan, alih-alih Constructor Dependency Injection yang hanya mengatakan setiap objek tersedia saat kelas dibuat.

Saya menggunakan ini untuk mengubah Akses Data Database saya ke lapisan Akses Data kode khusus ketika saya membuat Tes Unit. Saya tidak ingin Tes Unit saya berkomunikasi dengan database, server web, server email, dll. Mereka perlu menguji Layer Bisnis saya karena di situlah intelijen berada.


-4

Menggunakan injeksi dependensi jauh lebih baik menurut saya jika Anda: 1. menyebarkan kode Anda dalam partisi kecil, karena menangani dengan baik dalam decoupling satu kode besar. 2. testability adalah salah satu kasus DI ok untuk digunakan karena Anda dapat dengan mudah mengejek benda yang tidak dipisahkan. dengan penggunaan antarmuka, Anda dapat dengan mudah mengejek dan menguji setiap objek. 3. Anda dapat secara bersamaan merevisi setiap bagian dari program tanpa perlu kode bagian lain sejak itu dipisahkan secara longgar.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.