Rumah >Java >javaTutorial >Prinsip Inversi Ketergantungan

Prinsip Inversi Ketergantungan

王林
王林asal
2024-08-26 06:32:31816semak imbas

Modul peringkat tinggi tidak boleh bergantung pada modul peringkat rendah. Kedua-duanya harus bergantung pada abstraksi.

Abstraksi tidak harus bergantung pada butiran, butiran harus bergantung pada abstraksi.

Mari kita fahami modul peringkat tinggi dan modul peringkat rendah melalui contoh:

Dependency Inversion Principle

Dalam apl e-dagang seperti Flipkart pada tahap tinggi, ia boleh dikategorikan sebagai ProductCatalog, PaymentProcessor dan CustomerProfile (ini adalah beberapa fungsi perniagaan utama)
Fungsi perniagaan ini saling bergantung pada modul lain yang ditunjukkan dalam imej di atas.

Nota: modul di atas lebih dekat dengan fungsi perniagaan yang dipanggil modul peringkat Tinggi.
Modul di bahagian bawah adalah berhampiran dengan butiran pelaksanaan yang dipanggil modul tahap Rendah.

Modul peringkat rendah ialah SQLProductRepository, GooglePayService, WireTransfer, EmailSender dan VoiceDialer.

Jika kita menganggap CustomerProfile (modul Tahap Tinggi) dan modul Komunikasi sahaja, Komunikasi ialah modul peringkat Rendah tetapi jika kita menganggap Komunikasi, EmailSender dan VoiceDialer sahaja, Komunikasi menjadi modul Tahap Tinggi, dan EmailSender dan VoiceDialer ialah modul Tahap Rendah.

Maksudnya di sini konsep modul peringkat Tinggi dan Rendah bukanlah mutlak tetapi relatif.

Menurut imej di atas ProductCatalog bergantung pada SQLProductRepository iaitu modul peringkat tinggi bergantung pada modul peringkat rendah, tetapi ini secara langsung bercanggah dengan takrifan pertama DIP.


Mari ambil ProductCatalog → perhubungan SQLProductRepository dan menganalisisnya dengan lebih lanjut.

import java.util.List;
/*
 * High-Level module
*/
public class ProductCatalog {
    public void listAllProducts(){
        SQLProductRepository sqlProductRepository = new SQLProductRepository();
        List<String> allProductsNames = sqlProductRepository.getAllProductNames();
        //Display all products names
    }
}
/*
 * Low-level module 
*/
import java.util.Arrays;
import java.util.List;
public class SQLProductRepository {
    public List<String> getAllProductNames(){
        return Arrays.asList("soap","toothpaste");
    }
}

Oleh kerana ProductCatalog bergantung secara langsung pada SQLProductRepository ini jelas merupakan pelanggaran definisi DIP 1 (mengikut definisi kedua-dua modul peringkat Tinggi dan Rendah harus bergantung pada abstraksi)

Mari kita betulkan ini seperti definisi 1:

membuat antara muka ProductRepository

import java.util.List;

public interface ProductRepository {
    public List<String> getAllProductNames();
}

Melaksanakan antara muka ini dalam SQLProductRepository

/*
 * Low-level module 
*/
import java.util.Arrays;
import java.util.List;
public class SQLProductRepository  implements ProductRepository{
    @Override
    public List<String> getAllProductNames(){
        return Arrays.asList("soap","toothpaste");
    }
}

Akhir sekali untuk ProductCatalog modul tahap tinggi kami tidak boleh langsung membuat instantiate SQLProductRepository di dalamnya. Kami akan menggunakan kelas ProductFactory untuk perkara yang sama

public class ProductFactory {
    public static ProductRepository create(){
        return new SQLProductRepository();
    }
}

Kami akan menggunakan ProductFactory untuk membuat instantiate SQLProductRepository

/*
 * High-Level module
*/
import java.util.List;

public class ProductCatalog {
    public void listAllProducts(){
        ProductRepository productRepository = ProductFactory.create();
        List<String> allProductsNames = productRepository.getAllProductNames();
        //Display all products names
    }
}

Perhatikan objek rujukan kami ialah ProductRepository Jadi, kami tidak mempunyai gandingan yang ketat dengan SQLProductRepository

Selepas pengubahsuaian, kebergantungan baharu akan kelihatan seperti ini

Dependency Inversion Principle

Perubahan di atas adalah seperti definisi DIP 1.
Perubahan kod di atas juga mengikut takrifan ke-2 DIP juga iaitu Abstraksi tidak boleh bergantung pada butiran, butiran harus bergantung pada abstraksi.
Seperti yang dapat kita lihat dalam imej di atas SQLProductRepository bergantung pada ProductRepository bukan sebaliknya. Inilah sebab mengapa prinsip ini dipanggil Prinsip Inversi Ketergantungan


Suntikan Ketergantungan VS Penyongsangan Ketergantungan

Even though they are related, they are not the same and can not be used interchangeably 

Memahami Suntikan Ketergantungan:

Dalam ProductCatalog kami menggunakan kaedah Factory ProductFactory.create() untuk mendapatkan contoh objek SQLProductRepository.
Walaupun ia mewakilkan proses penciptaan contoh kepada kelas kilang ProductFactory, proses pemula masih dengan kelas ProductCatalog.
Sebaik-baiknya, kami tidak mahu kelas ProductCatelog bimbang tentang cara dan bila untuk mencetuskan instantiasi.
Bagaimana jika kami menyediakan kelas ProductRepository instan kepada ProductCatalog walaupun tanpa ia bertanya?

Jadi, kelas Utama ECommerceMainApplication menggunakan kaedah kilang ProductFactory.create() untuk mencipta tika ProductRepository dan tika ini diluluskan sebagai hujah dalam pembina kelas ProductRepositroy.

public class ECommerceMainApplication {
    public static void main(String agrs[]) {
        ProductRepository productRepository = ProductFactory.create();
        ProductCatalog productCatalog = new ProductCatalog(productRepository);
        productCatalog.listAllProducts();
    }
}

Selepas mengemas kini kelas ProductCatalog dengan sewajarnya

import java.util.List;

public class ProductCatalog {

    private ProductRepository productRepository;

    public ProductCatalog(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }

    public void listAllProducts(){
        List<String> allProductsNames = productRepository.getAllProductNames();
        //Display all products names
        allProductsNames.forEach(product-> System.out.println(product));
    }
}

Kini ProductCatalog bebas untuk menggunakan objek SQLProductRepository pada bila-bila masa dan di mana sahaja ia mahu. Ia tidak lagi bimbang tentang mencipta objek SQLProductRepository sendiri.
Dalam erti kata lain kami menyuntik kebergantungan ke dalam ProductCatalog dan bukannya ProductCatalog membimbangkan tentang membuat seketika kebergantungan.
Ini adalah konsep suntikan kebergantungan


Penyongsangan kawalan - IOC

Walaupun ia bukan sebahagian daripada DIP(Prinsip Penyongsangan Kebergantungan), ia berkait rapat

Mari kita fahami ini dengan kod yang sama di atas

Kelas ProductCatalog mempunyai pembina yang mengambil objek ProductRepository.

Kelas yang memanggil ProductCatalog akan menyediakan atau menyuntik objek ProductRepository dalam kes ini ia adalah ECommerceMainApplication.
Ambil perhatian, walaupun suntikan berlaku di luar kelas ProductCatalog, suntikan masih berlaku semasa aliran utama program. iaitu suntikan sedang berlaku dalam urutan utama pelaksanaan program.

Bagaimana jika kita mahu semua suntikan berlaku dalam urutan yang berasingan atau konteks yang berasingan sama sekali Supaya aliran kawalan utama diasingkan sepenuhnya daripada suntikan?

Ini boleh dicapai menggunakan rangka kerja seperti Spring(di Jawa).

Dependency Inversion Principle

Spring akan menjalankan konteksnya sendiri yang berbeza daripada aliran utama program
Spring akan menguruskan menyuntik kebergantungan yang diperlukan kelas. Jadi, jika anda ingin membuat instantiate objek kelas, bukannya melakukannya sendiri secara langsung dalam kod, anda meminta Spring memberikan objek kelas kepada anda.
Rangka kerja Spring melihat semua kebergantungan yang diperlukan untuk instantiasi objek, kemudian meneruskan dan menyuntik semua kebergantungan, membuat instantiate objek dan memberikannya kembali kepada aliran kawalan utama.
Oleh itu kawalan ke atas suntikan pergantungan diwakilkan sepenuhnya kepada rangka kerja Spring dan tidak berlaku dalam aliran kawalan mel.
Konsep ini dipanggil Inversion of Control (IOC) dan Spring dipanggil Inversion of Control Container atau ringkasnya IOC Container

Atas ialah kandungan terperinci Prinsip Inversi Ketergantungan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel sebelumnya:Prinsip Penggantian LiskovArtikel seterusnya:Prinsip Penggantian Liskov