依賴反轉原則


首先,什么是依賴反轉,為什么叫反轉?

高層不應該依賴細節,細節應該依賴高層。


什么是高層?什么是細節?對一個系統來說,業務邏輯是高層,其他是細節。業務邏輯是僅僅包括用例、業務實體部分,不包括任何框架、存儲(數據庫)、其他系統等部分,是純粹的。其他細節,包括框架、數據庫、消息隊列,都是細節。業務邏輯應該不依賴任何細節。細節的實現可以任意替換而不影響業務邏輯。這樣的業務邏輯,可以測試、容易測試。

拿通常的Java Web應用來說,一般我們使用的包括:Controller->Service->DAO->數據庫。 其中,Service是高層,包含業務邏輯,其他都是細節。

為什么叫“反轉”,從調用順序來講,Service是依賴DAO來實現業務數據的存取的,那么這時候高層就依賴了細節。但如果我們在Service層抽象一個DAO接口,讓實際的DAO從這個接口派生一個類出來。那么Service這個模塊就不依賴於DAO的實現,而是依賴了一個內部的接口。這樣調用的方向和依賴的方向就相反了,稱之為“反轉”。例子:【Service->IDAO】<-DAOImpl->數據庫。

依賴注入和依賴反轉的關系

依靠框架的依賴注入功能,我們很容易實現依賴反轉的時候實現實例的注入。

業務對象:

public class QuizServiceImpl implements QuizService {
    private BankDAO bankDAO;
    private QuizDAO quizDAO;

 在業務對象里面,我們定義了兩個DAO,都是接口。

在外部實現的時候,我們首先派生兩個對象,實現這兩個DAO接口。然后用Spring的Configuration功能,將這些接口的實現注入到Service中。Service完全不知道Spring框架、數據庫的存在,他只關注自己的業務邏輯,以及自己聲明的兩個DAO接口。

@Configuration
public class ServiceConfig {
    @Bean
    BankDAO bankDAO(){
        return new MemoryBankDAOImpl();
    }
    @Bean
    QuizDAO quizDAO(){
        return new MemoryQuizDAOImpl();
    }
    @Bean
    QuizService quizService(BankDAO bankDAO,QuizDAO quizDAO){
        QuizServiceImpl quizService=new QuizServiceImpl();
        quizService.setBankDAO(bankDAO);
        quizService.setQuizDAO(quizDAO);
        return quizService;
    }
    @Bean
    QuestionAdminService questionAdminService(BankDAO bankDAO){
        QuestionAdminServiceImpl questionAdminService=new QuestionAdminServiceImpl();
        questionAdminService.setBankDAO(bankDAO);
        return questionAdminService;
    }
}

  這樣我們就可以在Controller等地方,使用@Autowired對QuiService進行自動注入。而Service完全不知道這些細節的存在!當然也就不存在依賴。

通過依賴反轉,高層的業務邏輯和各種細節完全解耦。你甚至可以這么做:一個工程寫業務邏輯,然后打包成一個jar,另外一個實現的工程引用這個jar,把數據庫、Controller等實現了,完成完整功能。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM