이펙티브 자바 - item 5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
on JAVA
이펙티브 자바 - item 5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
클래스들이 자원(다른 클래스)에 의존하는 경우가 있다. 예를들어 SpellChecker 클래스가 dictionary 유틸리티 클래스를 사용한다고 가정한다.
유틸리티 클래스
public class SpellChecker {
private static final Lexicon dictionary = ...;
private SpellChecker() {} // 인스턴스화 방지 (아이템 4 참고)
public static boolean isVaild(String word) {...}
public static List<String> suggestions(String typo) {...}
}
싱글턴
public class SpellChecker {
private final Lexicon dictionary = ...;
private SpellChecker() {} // 인스턴스화 방지 (아이템 4 참고)
public static SpellChecker INSTANCE = new SpellChecker(...);
public static boolean isVaild(String word) {...}
public static List<String> suggestions(String typo) {...}
}
두 방법 모두 확장에 유연하지 않고 테스트가 어렵다.
기본적으로 멀티스레드 환경에서는 사용할 수 없으며, 사전은 굉장히 여러 종류가 있는데(한국어 사전, 영어 사전, 특수 어휘용 사전 등…) dictionary 하나로만 이 역할을 모두 수행하기에는 어렵고 SpellChecker는 dictionary 하나만 사용할 수 있기 때문이다.
사용하는 자원에 따라 동작이 달라지는 클래스는 위 두 방법이 적합하지 않다.
의존 객체 주입
public class SpellChecker {
private final Lexicon dictionary;
// 여기서 의존성 주입을!
public SpellChecker(Lexicon dictionary){
this.dictionary = Objects.requireNotNull(dictionary);
}
public static boolean isVaild(String word) {...}
public static List<String> suggestions(String typo) {...}
}
장점
- 불변 보장
- 여러 클라이언트가 의존 객체들을 안심하고 공유 할 수 있다(멀티 스레드 환경)
- 의존 객체 주입은 생성자 뿐만 아니라, 정적 팩터리, 빌더 모두 똑같이 응용이 가능하다
의존 객체 주입 패턴 활용 - 참조할 자원의 팩토리를 주입하기
자바8에서 제공되는 Supplier
단점
의존 객체 주입은 유연성과 테스트 용이성을 개선해주나, 의존성이 수 천개나 되는 큰 프로젝트에서는 오히려 코드를 어지럽게 만들기도 한다.
보통 스프링 프레임워크같은 의존 객체 주입 프레임워크를 사용해 이러한 단점을 해결한다.