[아이템 5] 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
2021. 3. 23. 12:42ㆍJava/Effective Java
자원을 직접 명시하지 말고 의존 객체 주입을 사용하라자원을 직접 명시하지 말고 의존 객체 주입을 사용하라
- 클래스가 내부적으로 하나 이상의 자원에 의존하고 자원이 클래스 동작에 영향을 준다면 싱글턴과 정적 유틸 클래스는 사용하지 않는 것을 권장
- 자원에 따라 동작이 달라진다면, 자원의 수만큼 인스턴스를 만들어 동작하게 하는 것이 좋음
- 자원을 직접명시하지 말고 의존 객체 주입을 사용 권장
- Spring 과 같은 프레임워크에서 DI의 개념으로 많이 쓰임
사용하는 자원에 따라 동작이 달라지는 클래스에는 정적 유틸리티 클래스나 싱글턴 방식이 적합하지 않다.
- 아래의 예제는 사전을 단 하나만 사용한다면 좋은 코드
- 실전에서는 사전은 굉장히 여러 종류가 있으며 (한국어 사전, 영어 사전, 특수 어휘용 사전 등...) 특수 어휘용 사전을 별도로 두기도 한다. 심지어 테스트용 사전도 필요할 수 있다
- dictionary 하나로만 이 역할을 모두 수행하기에는 어렵다.
정적 유틸리티를 잘못 사용한 예제
public class SpellChecker {
private static final Lexicon dictionary = ...;
// 객체 생성 방지
private SpellChecker() {
}
public static boolean isValid(String word) {
...
}
public static List<String> suggestions (String typo) {
...
}
}
// 사용
SpellChecker.isValid(word);
List<String> test = SpellChecker.suggestion(typo)
싱글톤 잘못 사용한 예제
public class SpellChecker {
private final Lexicon dictionary = ...;
// 객체 생성 방지
private SpellChecker() {
}
public static SpellChecker INSTANCE = new SpellChecker(...);
public static boolean isVaild(String word) {
...
}
public static List<String> suggestions(String typo) {
...
}
}
// 사용
SpellChecker.INSTANCE.isValid(word);
List<String> test = SpellChecker.INSTANCE.suggestions(typo);
의존 객체 주입
- 인스턴스를 생성할 때 생성자에게 필요한 자원을 넘겨주는 방식
- 자원을 (혹은 그 자원을 만들어주는 팩토리를) 생성자 (혹은 정적 팩토리나 빌더에) 넘겨주는 방식
장점
- 불변을 보장
- 클래스의 유연성, 재사용성, 테스트 용이성을 개선
- 생성자, 정적 팩터리, 빌더 모두에 똑같이 응용할 수 있다.
단점
- 의존성 주입은 유연성과 테스트 용이성을 개선해주지만, 의존성이 너무 많아지면 코드가 장황해질 수도 있다.
의존 객체 주입 예제
- 클래스(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) {...}
}
// 인터페이스
interface Lexicon {}
// Lexicon 상속 받아서 구현
public class koreaDictionary implements Lexicon {
...
}
Lexicon dictionary = new koreaDictionary();
SpellChecker spellChecker = new SpellChecker(dictionary);
spellChecker.isVaild(word);
'Java > Effective Java' 카테고리의 다른 글
[아이템 47] 반환 타입으로는 스트림보다 컬렉션이 낫다 (0) | 2023.05.31 |
---|---|
[아이템 46] 스트림에서는 부작용 없는 함수를 사용하라 (0) | 2023.05.30 |
[아이템 45] 스트림은 주의해서 사용하라 (1) | 2023.05.17 |
[아이템 43] 람다보다는 메서드 참조를 사용하라 (0) | 2023.05.13 |
[아이템 42] 익명 클래스보다는 람다를 사용하라 (0) | 2023.05.12 |