여러 자원에 의존하고, 자원에 의해 동작이 달라지는 클래스는 의존 객체 주입을 사용하자
정적 유틸리티, 싱글턴 방식
다른 자원에 의존하는 클래스가 있을 때, 클래스 내부에서 이를 생성하여 (명시)하는 경우가 많다.
정적 유틸리티로 구현하거나, 싱글턴으로 구현하는 경우 의존 클래스를 하나만 사용한다는 가정이 있어야한다.
하지만 실제로는 의존 클래스가 여러 용도에 따라 다르게 필요할 수 있어, 유연성이 떨어지고 테스트하기도 어렵다.
즉, 사용 자원에 따라 동작이 달라지는 클래스의 경우 적합하지 않다.
// 정적 유틸리티
public class SpellChecker {
private static final Lexicon dictionary = ...;
private SpellChecker() {} // 객체 생성 방지용 private 생성자
public static boolean isValid(String word) { ... }
public static List<String> suggestions(String typo) { ... }
}
// 싱글턴
public class SpellChecker {
private static final Lexicon dictionary = ...;
private SpellChecker() {} // 객체 생성 방지용 private 생성자
public static SpellChecker INSTANCE = new SpellChecker(...);
public boolean isValid(String word) { ... }
public List<String> suggestions(String typo) { ... }
}
의존 객체 주입 방식 (Dependency Injection, DI)
인스턴스를 생성할 때 생성자에 필요한 지원을 넘겨주는 방식, 의존 객체를 유연하게 처리할 수 있다.
- 의존 자원의 개수, 관계와 상관 없이 작동
- 생성자뿐 아니라 정적 팩터리, 빌더 등에 응용 가능
- 의존이 달라져도 SpellChecker 코드 수정할 필요 없음
public class SpellChecker{
private final Lexicon dictionary; // final 필드로 받음, 불변
// 의존 객체 dictionary를 주입 받음
public SpellChecker(Lexicon dictionary){
this.dictionaryy = Objects.requireNonNull(dictionary);
}
public boolean isValid(String word) { ... }
public List<String> suggestions(String typo) { ... };
}
의존 객체 주입 변형 - 자원 팩터리
팩터리 - 인스턴스를 생성하는 객체
기존 의존 객체 주입에서는 객체를 직접 주입했었는데, 그 대신 팩터리를 주입하는 방식
- 매번 새로운 객체를 동적으로 주입할 수 있음
- Mock 객체를 쉽게 주입 가능
// 팩터리
@FunctionalInterface
public interface LexcionFactory {
Lexcion create();
}
// 팩터리 주입 방식
public class SpellChecker {
private final LexiconFactory lexiconFactory;
public SpellChecker(LexiconFactory lexiconFactory) {
this.lexiconFactory = Objects.requireNonNull(lexiconFactory);
}
public void checkSpelling(String word) {
Lexicon lexicon = lexiconFactory.create(); // 필요할 때마다 새로운 Lexicon 생성
}
}
// 실제 사용
// 한국어
SpellChecker koreanSpellChecker = new SpellChecker(KoreanDictionary::new);
// 영어
SpellChecker englishSpellChecker = new SpellChecker(EnglishDictionary::new);
반응형
'도서 > 이펙티브 자바' 카테고리의 다른 글
| [이펙티브 자바] 7. 다 쓴 객체 참조를 해제하라 (0) | 2025.03.21 |
|---|---|
| [이펙티브 자바] 6. 불필요한 객체 생성을 피하라 (0) | 2025.03.20 |
| [이펙티브 자바] 4. 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2025.03.03 |
| [이펙티브 자바] 3. private 생성자나 열거 타입으로 싱글턴임을 보증하라 (0) | 2025.02.22 |
| [이펙티브 자바] 2. 생성자에 매개변수가 많다면 빌더를 고려하라 (0) | 2025.02.21 |