場景描述
假設我們要開發一個日誌記錄器元件,記錄日誌的方式可能有多種實現:控制檯輸出、檔案輸出、甚至是傳送到遠端伺服器。為了實現這個功能,我們可以定義一個 Logger
介面來抽象日誌記錄功能,然後根據不同的需求建立不同的實現類。
1. 介面注入的實現方式
首先,我們定義一個 Logger
介面和兩個實現類:ConsoleLogger
和 FileLogger
。
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);
}
}
現在,我們有了兩個日誌記錄的實現類:ConsoleLogger
和 FileLogger
。接下來,我們建立一個依賴 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可以在執行時選擇注入哪一個具體的實現類,比如 ConsoleLogger
或 FileLogger
。
- 松耦合:
BusinessService
類只依賴於Logger
介面,而不依賴具體的ConsoleLogger
或FileLogger
實現類。我們可以在未來輕鬆替換日誌記錄的實現,而無需修改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
類的程式碼。程式碼的耦合度高,不易於擴充套件和維護。
總結
實現類注入的高耦合度體現在程式碼對具體實現類的直接依賴上,一旦需要更換實現類,所有依賴這個實現類的地方都需要修改。而介面注入則透過依賴抽象介面,實現了松耦合,提升了程式碼的靈活性和擴充套件性。