프로그래밍/JAVA
[JAVA] Effective Java - 5. 자원을 직접 명시하지 말고 의존 객체 주입 사용
하나만알자
2022. 9. 14. 00:03
반응형
보통 클래스는 하나 이상의 자원에 의존한다.
예시가 생각나지 않아 책에 나온 예시를 참조 하였다.
맞춤법 검사기는 사전에 의존하게 되는데, 이런 클래스들을
유틸리티 클래스 또는 싱글턴으로 구현한 모습을 드물지않게 볼 수 있다.
// 정적 유틸리티
class SpellChecker {
private final Lexicon dictionary = new KoreanLexicon();
private SpellChecker() {}
public static boolean isValid(String word) {
//..
}
}
// 싱글턴
class SpellChecker {
private final Lexicon dictionary = new KoreanLexicon();
private SpellChecker() {}
public static SpellChecker INSTANCE = new SpellChecker();
public boolean isValid(String word) {
//..
}
}
두 케이스 모두 잘못사용한 예로 들 수 있다. -> 사전을 국어사전만 사용할 수 있음.
이때, 여러 사전을 사용할 수 있도록 사전을 교체하는 메서드(setter)를 추가하게 되면 오류를 유발할 수 있고,
멀티스레드 환경에서는 사용할 수 없다.(불변 보장X)
사용하는 자원에 따라 동작이 달라지는 클래스의 경우에는 정적 유틸리티 클래스, 싱글턴 클래스 방식이 적절하지않다.
대안으로 의존 객체 주입이 있다.
인스턴스를 생성할 때, 생성자에 필요한 자원을 넘겨주는 방식
// 의존성 주입
class SpellChecker {
private final Lexicon dictionary;
public SpellChecker(Lexicon dictionary) {
this.dictionary = Objects.requireNonNull(dictionary);
}
public static boolean isValid(String word) {
//..
}
}
자원이 몇개든 의존관계가 어떻든 상관없이 잘 작동하고
불변을 보장하여 여러 클라이언트가 안심하고 사용 가능하다.
생성자, 정적 팩터리, 빌더 모두 적용가능.
생성자에 자원 팩터리를 넘겨주는 방식도 가능
class Mosaic {
public static Mosaic create(Supplier<? extends Tile> tileFactory) {
Tile tile = tileFactory.get();
// ..
}
}
// 상위 타입
interface Tile {
void setColor(String color);
}
// 하위 타입
class CheckTile implements Tile {
public void setColor(String color) {}
}
// 검은색 컬러 속성을 가지게 하는 객체 자원 팩터리를 넘겨준다.
Mosaic m = Mosaic.create(() -> {
CheckTile checkTile = new CheckTile();
checkTile.setColor("black");
return checkTile;
});
명시된 타입의 하위 타입이라면 무엇이든 생성할 수 있는 팩터리를 넘길 수 있다.
의존성이 많아지면 코드를 어지럽게 만들기도 한다.
스프링같은 프레임워크를 사용하면 간단하게 해소할 수 있다.
반응형