728x90
반응형
아이템 5 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
- 클래스가 하나 이상의 자원에 의존
- ex. 맞춤법 검사기(SpellChecker) -> 사전(Lexicon)에 의존
- 정적 유틸리티 클래스 or 싱글턴으로 자원 직접 지정 -> 유연성 ↓, 테스트 어려움
잘못된 접근
1) 정적 유틸리티
사전 교체 X -> 다국어, 테스트용 Mock 어려움
public class SpellChecker {
private static final Lexicon dictionary = ...;
private SpellChecker() {} // 객체 생성 방지
public static boolean isValid(String word) {...}
pbulic static List<String> suggestions(String typo) {...}
}
2) 싱글턴
특정 사전에 고정 -> 확장성 ↓
public class SpellChecker {
private final Lexicon dictionary = ...;
private SpellChecker(...) {}
public static SpellChecker INSTANCE = new SpellChecker(...);
public boolean isValid(String word) {...}
public List<String> suggestions(String typo) {...}
}
3) `Setter`로 교체 시도
`SpellChecker`가 여러 사전 사용할 수 있도록 수정
- `dictionary`를 교체할 수 있도록 `final` 제거 및 `setter` 추가
- (-) 어색하고 오류 발생 가능성 ↑
- (-) 멀티 스레드 환경에서 안전 X
=> 사용하는 자원에 따라 동작이 달라지는 클래스에서는 정적 유틸리티 or 싱글턴 방식 적합 X
해결 방법: 의존 객체 주입
- 자원을 외부에서 주입 -> 유연성, 테스트 용이성 확보
- 생성자에 의존 객체 전달
public class SpellChecker {
private final Lexicon dictionary;
public SpellChecker(Lexicon dictionary) {
this.dictionary = Objects.requireNonNull(dictionary);
}
public boolean isValid(String word) {...}
public List<String> suggestions(String typo) {...}
}
- 다양한 사전 교체 O (다국어 지원, 테스트용 Mock)
- `dictionary` 하나의 자원만 사용하지만, 자원 개수와 의존 관계에 상관 X 작동
- 불변 필드 -> 스레드 안전성 보장
- (같은 자원 사용하려는) 여러 클라이언트가 의존 객체 안심하고 공유 O
- 생성자, 정적 팩터리, 빌더 모두 응용 O
응용: 팩터리 메서드 & `Supplier`
- 자원 즉시 제공 X 필요할 때마다 생성해야 한다면 팩터리 사용
=> 팩터리 메서드 패턴: 생성자에 자원 팩터리 넘겨주는 방식
팩터리: 호출할 때마다 틀정 타입의 인스턴스를 반복해서 만들어주는 객체
- ex. 클라이언트가 제공한 팩터리가 생성한 타일(Tile)들로 구성된 모자이크(Mosaic) 만드는 메서드
`Mosaic create(Supplier<? extends Tile> tileFactory) {...}`
- ex. 클라이언트가 제공한 팩터리가 생성한 타일(Tile)들로 구성된 모자이크(Mosaic) 만드는 메서드
- `Supplier<T>`: 클라이언트가 원하는 타입의 하위 타입도 주입 O
- 일반적으로 한정적 와일드 카드 타입(bounded wild card type) 사용 -> 팩터리의 타입 매개변수를 제한해야 함
의존 객체 주입
- (+) 유연성, 테스트 용이성 개선
- (-) 코드가 복잡해질 수 있음
- (해결) DI 프레임워크(대거(Dagger), 주스(Guice), 스프링(Spring)) 활용
핵심 정리
- 클래스가 내부적으로 하나 이상의 자원에 의존, 그 자원이 클래스 동작에 영향 O
-> 싱글턴, 정적 유틸리티 클래스 사용 X, 클래스가 직접 만들게 X - 해결책: 의존 객체 주입
- 필요한 자원들 or 그 자원을 만들어주는 팩터리 -> 생성자, 정적 팩터리, 빌더 ~> 외부에서 주입
- => 클래스의 유연성, 재사용성, 테스트 용이성 개선
728x90
반응형