自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深度解讀架構(gòu)設(shè)計(jì)中的依賴反轉(zhuǎn)原則

開發(fā) 前端
通過一個(gè)小場(chǎng)景探討了傳統(tǒng)架構(gòu)設(shè)計(jì)中存在的不足,以及如何基于依賴反轉(zhuǎn)原則來對(duì)其進(jìn)行改進(jìn)。最后,我們基于Java代碼示例來展示了如何在代碼級(jí)別來實(shí)施依賴反轉(zhuǎn)原則。

在日常工作中,總是聽大家說使用依賴反轉(zhuǎn)原則可以很好地讓業(yè)務(wù)領(lǐng)域?qū)优c基礎(chǔ)設(shè)施或框架層進(jìn)行解耦。即使基礎(chǔ)設(shè)施發(fā)生變動(dòng),也不會(huì)影響業(yè)務(wù)領(lǐng)域代碼。那么架構(gòu)中所說的依賴反轉(zhuǎn)原則到底是什么呢?在寫代碼時(shí),我們又該如何實(shí)施呢?這節(jié)課,我們就來一探究竟。

DIP 原則是什么?

首先,我們來看下架構(gòu)中的依賴反轉(zhuǎn)原則是什么。根據(jù)維基百科的描述,依賴反轉(zhuǎn)原則(Dependency inversion principle,DIP)是指一種模塊解耦的實(shí)現(xiàn)思想,它使得高層次的模塊不依賴于低層次的模塊的實(shí)現(xiàn)細(xì)節(jié),從而使得低層次模塊依賴于高層次模塊的抽象。

這一原則的核心思想有如下兩點(diǎn):

  • 高層次的模塊不應(yīng)該依賴于低層次的模塊,兩者都應(yīng)該依賴于 抽象接口;
  • 抽象接口不應(yīng)該依賴于具體實(shí)現(xiàn),而具體實(shí)現(xiàn)則應(yīng)該依賴于抽象接口。

接下來,我們通過一個(gè)例子來深入理解一下這兩點(diǎn)思想。

當(dāng)Application模塊需要使用Service模塊提供的服務(wù)時(shí),傳統(tǒng)架構(gòu)上的設(shè)計(jì)是在Service模塊中定義ComputeService接口以及它的實(shí)現(xiàn)類ComputeServiceImpl。

這時(shí)Application模塊要想使用Service模塊的ComputeService服務(wù),就需要在Application模塊內(nèi)引入Service模塊,具體來說,在Java中是需要在Application模塊的POM文件里引入Service模塊的Maven倉庫坐標(biāo),然后Application模塊就可以引用到Service模塊的服務(wù)了。

圖片

設(shè)計(jì)完畢后,我們會(huì)得到兩個(gè)意義上的依賴關(guān)系。首先,從控制流上(代碼運(yùn)行時(shí)代碼的執(zhí)行時(shí)序上),Application模塊會(huì)依賴Service模塊;其次,代碼依賴上,Application模塊也會(huì)依賴Service模塊。

由于這種設(shè)計(jì)會(huì)導(dǎo)致Application模塊在源碼上就依賴了Service模塊,所以當(dāng)Service模塊修改、發(fā)布時(shí),Application模塊也需要修改和重新編譯,這顯然不是我們想要的。

而在采用DIP原則的情況下,相同場(chǎng)景下的設(shè)計(jì)如下圖:

圖片

如圖可知,我們把Application模塊所需的ComputeService接口定義到了Application模塊內(nèi)部,而ComputeService接口的具體實(shí)現(xiàn)類ComputeServiceImpl則放到了Service模塊。由于ComputeServiceImpl類需要實(shí)現(xiàn)ComputeService接口,所以Service模塊必須在源碼上依賴Application模塊。在Java中則體現(xiàn)為Service模塊的POM文件中要添加Application模塊的maven倉庫坐標(biāo),以及ComputeServiceImpl類要使用Application模塊的ComputeService接口代碼。

在基于DIP原則設(shè)計(jì)完畢后,我們也會(huì)得到兩個(gè)意義上的依賴關(guān)系。首先,從控制流上,Application模塊還是會(huì)依賴Service模塊;從代碼依賴上看,Service模塊也依賴Application模塊了。這體現(xiàn)了抽象接口(ComputeService)不應(yīng)該依賴于具體實(shí)現(xiàn)(ComputeServiceImpl),而具體實(shí)現(xiàn)類(ComputeServiceImpl)則應(yīng)該依賴于抽象接口(ComputeService)。另外,這里控制流上的依賴與源碼的依賴關(guān)系是相反的,所以叫做依賴反轉(zhuǎn)。

使用DIP原則,當(dāng)?shù)蛯哟蜸ervice模塊的ComputeServiceImpl類發(fā)生改動(dòng)時(shí),我們可以保證只需要修改和編譯Service模塊就可以了,Application模塊并不會(huì)受到影響。當(dāng)然如果ComputeService接口本身定義發(fā)生變化了,還是需要Application模塊進(jìn)行修改的。因此,請(qǐng)注意,使用DIP原則的前提也是接口是穩(wěn)定的情況下進(jìn)行討論的。

如何在代碼層面來實(shí)踐 DIP 原則?

下面,我們通過一個(gè)代碼示例來看看如何在實(shí)踐上基于DIP原則實(shí)現(xiàn)上面的場(chǎng)景。

圖片

這個(gè)Demo分為三個(gè)模塊,其中Application模塊、Service模塊分別對(duì)應(yīng)我們前面一直講解的兩個(gè)模塊,Main模塊的作用是用來提供main函數(shù)入口,用來把Application模塊和Service模塊的功能串起來,實(shí)現(xiàn)一個(gè)可執(zhí)行的程序。

三個(gè)模塊之間的依賴關(guān)系如下圖:

圖片

首先,我們來看下Application模塊的內(nèi)容。

圖片

可以看到,Application模塊下有兩個(gè)類,其中ComputeService接口定義為:

public interface ComputeService {
  int add(int a, int b);
}

ApplicationService的代碼如下:

public class ApplicationService {
  private ComputeService computeService;
  public ApplicationService(ComputeService computeService) {
    this.computeService = computeService;
  }
  public int add(int a, int b) {
    return computeService.add(a, b);
  }
}

ApplicationService服務(wù)依賴了ComputeService接口來具體實(shí)現(xiàn)add操作,這里ComputeService接口就是抽象接口。后面我們會(huì)講到,無論Application模塊還是Service模塊,都只會(huì)依賴ComputeService這個(gè)抽象接口。

我們?cè)?Application模塊目錄下執(zhí)行mvn clean install命令,就可以把Application模塊安裝到本地Maven倉庫,然后其他模塊就可以通過它的Maven坐標(biāo)引用這個(gè)服務(wù)了。

<dependency>
  <groupId>org.example</groupId>
  <artifactId>Application</artifactId>
  <version>1.0-SNAPSHOT</version>
  <scope>compile</scope>
</dependency>

然后我們看下Service模塊的內(nèi)容。

圖片

Service模塊下只包含ComputeServiceImpl一個(gè)類,它的代碼內(nèi)容如下:

public class ComputeServiceImpl implements ComputeService {
  @Override
  public int add(int a, int b) {
    return a + b;
  }
}

可以看到,ComputeServiceImpl類實(shí)現(xiàn)了ComputeService抽象接口。由于ComputeServiceImpl類依賴ComputeService接口的源碼,所以我們需要在Service模塊的POM文件里面添加Application模塊的依賴,也就是添加下面的Maven坐標(biāo):

<dependency>
  <groupId>org.example</groupId>
  <artifactId>Application</artifactId>
  <version>1.0-SNAPSHOT</version>
  <scope>compile</scope>
</dependency>

ComputeServiceImpl類的實(shí)現(xiàn)比較簡單,就是簡單計(jì)算加法,然后返回結(jié)果。這里我們需要知道的是,因?yàn)镃omputeService接口的定義在Application模塊,所以Service模塊在源碼上就依賴了Application模塊。最后在Service模塊的目錄下執(zhí)行mvn clean install 命令就可以把Service模塊安裝到本地Maven倉庫,然后其他模塊就可以通過其Maven坐標(biāo)引用這個(gè)服務(wù)了。

<dependency>
  <groupId>org.example</groupId>
  <artifactId>Service</artifactId>
  <version>1.0-SNAPSHOT</version>
</dependency>

下面,我們?cè)倏碝ain模塊的內(nèi)容。

圖片

Main模塊內(nèi)就含有一個(gè)叫做Main的類,對(duì)應(yīng)代碼如下:

public class Main {
  public static void main(String[] args) {
    //1. 創(chuàng)建計(jì)算服務(wù)
    ComputeService computeService = new ComputeServiceImpl();
    //2. 創(chuàng)建應(yīng)用服務(wù)
    ApplicationService applicationService = new ApplicationService(computeService);
    //3. 執(zhí)行計(jì)算,并輸出結(jié)果
    int result = applicationService.add(1,2);
    System.out.println(result);
  }
}

代碼1創(chuàng)建了一個(gè)ComputeServiceImpl服務(wù)的實(shí)例,由于ComputeServiceImpl的實(shí)現(xiàn)在Service模塊里,所以我們需要在Main組件的POM文件里,填寫下面的Maven坐標(biāo):

<dependency>
  <groupId>org.example</groupId>
  <artifactId>Service</artifactId>
  <version>1.0-SNAPSHOT</version>
</dependency>

代碼2則創(chuàng)建了一個(gè)ApplicationService實(shí)例,并且把代碼1創(chuàng)建的ComputeServiceImpl實(shí)例作為參數(shù)。這里我們需要注意的是,ApplicationService的構(gòu)造函數(shù)的入?yún)镃omputeService接口,而不是ComputeServiceImpl。這體現(xiàn)了高層次的Application模塊不應(yīng)該依賴于低層次的Service模塊(ComputeServiceImpl類),兩者都應(yīng)該依賴于 抽象接口(ComputeService)。

另外,代碼2由于依賴ApplicationService的源碼,所以Main組件還是需要依賴Application模塊,這就需要在Main組件的POM文件中,添加Application模塊的Maven坐標(biāo):

<dependency>
  <groupId>org.example</groupId>
  <artifactId>Application</artifactId>
  <version>1.0-SNAPSHOT</version>
  <scope>compile</scope>
</dependency>

代碼3就比較簡單了,我們直接調(diào)用Application模塊的ApplicationService的add方法執(zhí)行計(jì)算。調(diào)用ApplicationService的add方法后,add方法內(nèi)部則會(huì)調(diào)用Service模塊的ComputeServiceImpl類的add方法執(zhí)行具體計(jì)算操作。

總結(jié)

這次我們先學(xué)習(xí)了什么是依賴反轉(zhuǎn)原則。然后,通過一個(gè)小場(chǎng)景探討了傳統(tǒng)架構(gòu)設(shè)計(jì)中存在的不足,以及如何基于依賴反轉(zhuǎn)原則來對(duì)其進(jìn)行改進(jìn)。最后,我們基于Java代碼示例來展示了如何在代碼級(jí)別來實(shí)施依賴反轉(zhuǎn)原則。

責(zé)任編輯:武曉燕 來源: 程序猿技術(shù)充電站
相關(guān)推薦

2021-05-07 15:27:23

架構(gòu)設(shè)計(jì)架構(gòu)開發(fā)

2015-10-29 10:50:46

Android架構(gòu)設(shè)計(jì)原則

2023-07-09 15:24:05

架構(gòu)設(shè)計(jì)思想AKF

2021-11-01 21:01:01

架構(gòu)設(shè)計(jì)軟件

2012-05-11 10:38:15

Cloud Found

2023-05-12 07:52:13

架構(gòu)設(shè)計(jì)設(shè)計(jì)原則

2024-08-16 14:01:00

2024-05-10 07:19:46

IOC依賴倒置控制反轉(zhuǎn)

2024-09-09 09:00:12

架構(gòu)設(shè)計(jì)算法

2009-07-06 10:36:41

敏捷開發(fā)

2024-09-19 08:46:46

SPIAPI接口

2023-07-17 15:09:08

SaaS架構(gòu)平臺(tái)

2017-05-17 14:51:31

DNS架構(gòu)負(fù)載均衡

2012-03-07 10:40:19

Java設(shè)計(jì)模式

2025-04-15 04:00:00

2022-12-30 08:16:34

2013-09-02 17:53:41

MVC架構(gòu)設(shè)計(jì)MEF

2020-08-27 14:22:29

MySQL數(shù)據(jù)庫架構(gòu)設(shè)計(jì)

2022-03-29 15:10:22

架構(gòu)設(shè)計(jì)模型

2013-05-27 10:58:28

Tumblr架構(gòu)設(shè)計(jì)雅虎收購
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)