2020/06/28

[筆記] Effective Java #5 優先考慮 dependency injection 來引用資源

Effective Java 3rd 簡體中文版筆記 #5 優先考慮 dependency injection 來引用資源
在 OOP 的情境下,通常一個 class 會需要其它資源的協助,假定 UserChecker 是驗證使用者身分的服務,它需要負責驗證機制的 class 來確認使用者身分。驗證機制為 AuthMechanism。然後將 UserChecker 當作像工具類別 (Utility class) 來處理。
public class UserChecker {
    private static final AuthMechanism mechanism = new AuthMechanism();
    private UserChecker() { }

    public static boolean login(String username, String password) { ... }
}
當然也可以將 UserChecker 採用 singleton 作法。
public class UserChecker {
    private final AuthMechanism mechanism = ...;
    private UserChecker(...) { }
    public static final UserChecker INSTANCE = new UserChecker(...);
    
    public boolean login(String username, String password) { ... }
}
以上兩種作法都不理想,因為它們都假設只會有一種 AuthMechanism 可用,當 AuthMechanism 有多種實作時,像是 hashed password 驗證方式,OAuth 驗證方式等。UserChecker 若要支援多種 AuthMechanism,上面兩種架構就較難擴充,而且在測試上,static 物件比較難作測試。Utility class 及 singleton class 不適合當作引用資源的方式

其實最簡單的方式就是將 AuthMechanism 傳入 UserChecker 的 constructor,而 UserChecker 不需要去負責生成它需要的資源,這就是 dependency injection。當作資源的 class 需為 immutable,讓更多不同的 class 可以共享它們,dependency injection 可以適用在 constructor、static factory 及 builder。
public class UserChecker {
    private final AuthMechanism mechanism;
    private UserChecker(AuthMechanism mechanism) {
        this.mechanism = mechanism;
    }

    public boolean login(String username, String password) { ... }
}
雖然 dependency injection 的設計方式較靈活,較容易進行測試,但在大型專案下,有非常多的 dependency 需要設定,這樣往往會讓架構越來越凌亂,所以可以使用套件來管理 dependency injection 這件事,最常見的就是 Spring Framework
Spring Framework
https://spring.io/projects/spring-framework
轉載請註明原文網址 https://cookieandcoketw.blogspot.com/2020/06/effective-java-5-dependency-injection.html

沒有留言:

張貼留言