整理Effective Java書中Item 5: Prefer dependency injection to hardwiring resources心得筆記

主旨

這篇在呼應item3提到的singleton以及item4中utils class的問題,建議使用依賴注入(dependency injection)。

點出問題

Static utility classes and singletons are inappropriate for classes whose behavior is parameterized by an underlying resource.

Static utility classes and singletons這兩種不適合使用參數取得底層資源,舉個白話一點的例子,今天需求是驗證信用卡卡號是否合法,你寫了一個utils class也遵照了item4提出的建議,很快地做完了。

public class CreditCardValidator {

    private static final CreditCard creditCard = new VisaCard();

    private CreditCardValidator() {
        throw new IllegalStateException("Utility class");
    }

    public static boolean isValid(String cardNumber) {
        ...
    }

}

後來需求增除了驗證VISA卡也要可以驗證Master跟JCB,這時候才發現原本的方法好像不適用。這時候你需要的是支持傳遞參數透過constructor來實例化的架構。

public class CreditCardValidator {

    private final CreditCard creditCard;

    public CreditCardValidator(CreditCard creditCard) {
        this.creditCard = Objects.requireNonNull(creditCard);
    }

    public boolean isValid(String cardNumber) {
        ...
    }

}

透過CreditCardValidator validator = new CreditCardValidator(new JcbCard());調用達到需求,這種依賴注入(dependency injection)的方式簡單有彈性又具可測性,目前很多框架(如 Dagger、Guice 或 Spring)都讓我們更容易實現。

小結

盡量少用singleton和static class來時實現依賴多個底層資源,相反的,透過依賴注入的方式來將所需資源注入將大大增加靈活性、可重用性以及可測性。