클래스는 대부분 의존성을 지닌다. 이번 아이템에서는 의존 관계를 가지도록 설정하는 방법에 대해 다룬다.
방법1. 정적 유틸리티
: 유연하지 않고 테스트 하기 어렵다
// 부적절한 static 유틸리티 사용 예 - 유연하지 않고 테스트 할 수 없다.
public class SpellChecker {
private static final Lexicon dictionary = new KoreanDicationry();
private SpellChecker() {
// Noninstantiable
}
public static boolean isValid(String word) {
throw new UnsupportedOperationException();
}
public static List<String> suggestions(String typo) {
throw new UnsupportedOperationException();
}
}
interface Lexicon {}
class KoreanDicationry implements Lexicon {}
방법2. 싱글톤
: 유연하지 않고 테스트 하기 어렵다.
// 부적절한 싱글톤 사용 예 - 유연하지 않고 테스트 할 수 없다.
public class SpellChecker {
private final Lexicon dictionary = new KoreanDicationry();
private SpellChecker() {
}
public static final SpellChecker INSTANCE = new SpellChecker() {
};
public boolean isValid(String word) {
throw new UnsupportedOperationException();
}
public List<String> suggestions(String typo) {
throw new UnsupportedOperationException();
}
}
방법 1, 방법 2 모두 사전을 하나만 사용하기 때문에 테스트하거나 언어별로 사용하기에 적절하지 않다.
즉, 어떤 클래스가 사용하는 리소스에 따라 행동을 달리 해야 하는 경우에는 스태틱 유틸리티 클래스와 싱글톤을 사용하는 것은 부적절하다.
이를 해결하기 위한 패턴으로 생성자를 사용해서 새 인스턴스를 생성할 때 사용할 리소스를 넘겨주는 방법이 있다. 방법 3을 보자.
방법3. 의존 객체 주입
: 유연성과 테스트 용이성이 높다.
이 방식은 생성자, 정적 팩토리, 빌더 모두 적용할 수 있다.
public class SpellChecker {
private final Lexicon dictionary;
public SpellChecker(Lexicon dictionary) {
this.dictionary = Objects.requireNonNull(dictionary);
}
public boolean isValid(String word) {
throw new UnsupportedOperationException();
}
public List<String> suggestions(String typo) {
throw new UnsupportedOperationException();
}
}
class Lexicon {}
이 패턴의 변종으로 리소스의 팩토리를 생성자에 전달하는 방법(팩토리 메소드 패턴)도 있다. 이 방법은 자바 8에 들어온 Supplier<T> 인터페이스가 그런 팩토리로 쓰기에 완벽하다. Supplier<T>를 인자로 받는 메소드는 보통 bounded wildcard type(아이템 31)으로 입력을 제한해야 한다.
Mosaic create(Supplier<? extends Tile> tileFactory) { ... }
*팩토리
호출할 때마다 특정 타입의 인스턴스르 반복해서 만들어주는 객체
의존성 주입이 유연함과 테스트 용이함을 크게 향상시켜주지만, 의존성이 큰 프로젝트의 경우 코드가 장황해질 수 있다. 이 점은 스프링 프레임워크를 통해 해결할 수 있다.
스프링에서의 의존성 주입을 알고 싶다면 아래 포스트를 보자.
[Spring] 스프링 빈과 의존관계
거의 반년동안 스프링 스터디에서 진행하였던 블로그 프로젝트가 마무리가 되고 현재는 김영한님의 강의를 보면서 부족했던 부분을 보완하고 있다! 그 당시에 스프링을 처음 접하기도 하고 그
joyerim.tistory.com
요약
의존하는 리소스에 따라 행동을 달리하는 클래스를 만들 떄는 싱글톤이나 static 유틸 클래스를 사용하지 말자. 그런 경우에는 리소스를 생성자나 팩토리를 전달하는 의존성 주입을 사용하여 유연함, 재사용성, 테스트 용이성을 향상시키자.
'Language > Java' 카테고리의 다른 글
[effective java] 아이템 8. finalizer와 cleaner 사용을 피하라. (0) | 2023.03.08 |
---|---|
[effective java] 아이템 7. 다 쓴 객체 참조를 해제하라. (0) | 2023.03.04 |
[effective java] 아이템 4. 인스턴스화를 막으려거든 private 생성자를 사용하라. (0) | 2023.03.02 |
[effective java] 아이템 3. private 생성자나 열거 타입으로 싱글턴임을 보증하라. (0) | 2023.03.02 |
[effective java] 아이템 2. 생성자에 매개변수가 많다면 빌더를 고려하라. (0) | 2023.03.01 |