[아이템 5] 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라

ajufresh·2020년 3월 2일
1

Effective Java 3/E

목록 보기
5/9
post-thumbnail

백기선님 유튜브(이팩티브 자바 #5 의존성 주입)

클래스들이 자원(다른 클래스)에 의존하는 경우가 있다.
예를 들어서 SpellChecker라는 클래스에서 dictionary라는 유틸리티 클래스를 사용한다고 가정해보겠다.

1. 정적 유틸리티 클래스

public class SpellChecker {
	private static final Lexicon dictionary = ...;
    
    private SpellChecker() {} // 인스턴스화 방지 (아이템 4 참고)
    
    public static boolean isVaild(String word) {...}
    public static List<String> suggestions(String typo) {...}
}

//사용은 이렇게!
SpellChecker.isValid(word);

2. 싱글턴

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) {...}
}

//사용은 이렇게!
SpellChecker.INSTANCE.isValid(word);

두 방법 모두 확장에 유연하지 않고 테스트가 어렵다.

사전은 굉장히 여러 종류가 있는데(한국어 사전, 영어 사전, 특수 어휘용 사전 등...)
dictionary 하나로만 이 역할을 모두 수행하기에는 어렵고,
SpellChecker는 dictionary 하나만 사용할 수 있기 때문이다.

사용하는 자원에 따라 동작이 달라지는 클래스는 위 두 방법이 적합하지 않다.

그렇다면 아래와 같이 final을 삭제하고 사전을 교체하는 메소드를 작성하는 것은 어떨까?

public class SpellChecker {
	private static Lexicon dictionary = ...;
    
    ...
    public static void changeDictionary(Lexicon new) {
    	dictionary = new;
    }
    ...
}

//사용은 이렇게!
SpellChecker.changeDictionary(newDictionary);

-> 어색하고 멀티스레드 환경에서는 사용할 수 없다.

3. 의존 객체 주입의 형태

이 방법은 인스턴스를 생성할 때 생성자에게 필요한 자원을 넘겨주는 방식이다.
코드를 보는게 더 이해하기 편하다.

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 myDictionary implements Lexicon {
	...
}

// 사용은 이렇게!
Lexicon dic = new myDictionary();
SpellChecker chk = new SpellChecker(dic);

chk.isVaild(word);

이 패턴의 응용 방법으로는 생성자에 자원 팩토리를 넘겨주는 방식이 있다. (팩토리 메소드 패턴)
ex. Supplier

이처럼 의존성 주입은 유연성과 테스트 용이성을 개선해주지만, 의존성이 너무 많아지면 코드가 장황해질 수도 있다.

profile
공블로그

0개의 댓글