Spring使用實現類注入為什麼會導致高耦合度(舉例)

槑孒發表於2024-08-15

場景描述

假設我們要開發一個日誌記錄器元件,記錄日誌的方式可能有多種實現:控制檯輸出、檔案輸出、甚至是傳送到遠端伺服器。為了實現這個功能,我們可以定義一個 Logger 介面來抽象日誌記錄功能,然後根據不同的需求建立不同的實現類。

1. 介面注入的實現方式

首先,我們定義一個 Logger 介面和兩個實現類:ConsoleLoggerFileLogger

public interface Logger {
    void log(String message);
}

@Service
public class ConsoleLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("Console: " + message);
    }
}

@Service
public class FileLogger implements Logger {
    @Override
    public void log(String message) {
        // 這裡是將日誌寫入檔案的程式碼,簡單起見,先輸出到控制檯
        System.out.println("File: " + message);
    }
}

現在,我們有了兩個日誌記錄的實現類:ConsoleLoggerFileLogger。接下來,我們建立一個依賴 Logger 的業務類。

@Component
public class BusinessService {
    private final Logger logger;

    @Autowired
    public BusinessService(Logger logger) {
        this.logger = logger;
    }

    public void doBusiness() {
        logger.log("Business logic executed");
    }
}

在這個例子中,BusinessService 類依賴於 Logger 介面。透過介面注入,Spring可以在執行時選擇注入哪一個具體的實現類,比如 ConsoleLoggerFileLogger

  • 松耦合: BusinessService 類只依賴於 Logger 介面,而不依賴具體的 ConsoleLoggerFileLogger 實現類。我們可以在未來輕鬆替換日誌記錄的實現,而無需修改 BusinessService 類。

例如,如果業務需求發生變化,我們只需要將配置中的 ConsoleLogger 替換為 FileLogger,而 BusinessService 類不需要做任何修改。這體現了介面注入的靈活性和低耦合度。

2. 實現類注入的實現方式

現在,假設我們不使用介面,而是直接在 BusinessService 類中注入 ConsoleLogger 實現類:

@Component
public class BusinessService {
    private final ConsoleLogger consoleLogger;

    @Autowired
    public BusinessService(ConsoleLogger consoleLogger) {
        this.consoleLogger = consoleLogger;
    }

    public void doBusiness() {
        consoleLogger.log("Business logic executed");
    }
}

在這個版本中,BusinessService 類依賴於具體的 ConsoleLogger 實現類,而不是 Logger 介面。

  • 高耦合: BusinessService 現在與 ConsoleLogger 強耦合。如果將來業務需求要求我們使用 FileLogger,那麼我們不得不修改 BusinessService 類,將 ConsoleLogger 替換為 FileLogger。這就增加了程式碼的耦合度和維護成本。

換句話說,實現類注入使得依賴關係更加剛性。如果我們在多個地方都直接依賴 ConsoleLogger 實現類,那麼每次更換實現類時,我們都需要修改這些地方的程式碼。這不僅會導致工作量的增加,還容易出現錯誤和遺漏,維護成本較高。

3. 耦合度的比較

  • 介面注入的松耦合: BusinessService 只依賴於抽象的 Logger 介面,因此可以在不修改程式碼的情況下,靈活地更換不同的實現類。未來如果有新的需求,例如新增一個遠端日誌記錄器,只需新增一個 RemoteLogger 實現類,並配置Spring注入它,而無需修改現有的業務程式碼。

  • 實現類注入的高耦合: BusinessService 直接依賴於具體的 ConsoleLogger 實現類,這意味著每次更換實現類時都需要修改 BusinessService 類的程式碼。程式碼的耦合度高,不易於擴充套件和維護。

總結

實現類注入的高耦合度體現在程式碼對具體實現類的直接依賴上,一旦需要更換實現類,所有依賴這個實現類的地方都需要修改。而介面注入則透過依賴抽象介面,實現了松耦合,提升了程式碼的靈活性和擴充套件性。

相關文章