ch1.객체의 생성과 파괴

item5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라

의존 객체 주입을 사용하지 않은 예

1. 정적 유틸리티 클래스

public class SpellChecker {
    private static final Lexicon dictionary = new Lexicon();

    private SpellChecker() { }
    
    public static boolean isValid(String word) {
        return true;
    }
    
    public static List<String> suggestions(String typo) {
        return new ArrayList<>();
    }
}

2. 싱글턴

public class SpellChecker {
    private final Lexicon dictionary = new Lexicon();
    private SpellChecker() {}
    public static SpellChecker INSTANCE = new SpellChecker();
    
    public boolean isValid(String word) {
        return true;
    }
    
    public List<String> suggestions(String typo) {
        return new ArrayList<>();
    }
    
}

의존 객체 주입을 사용

위의 두 잘못된 예시처럼 Lexicon dictionary를 직접 명시하면 다른 ditonary를 사용하고 싶을때 수정이 어렵습니다. 사용하는 자원에 따라 동작이 달라지는 클래스는 정적 유틸리티 클래스, 싱글턴 방식이 적합하지 않습니다. 사용하는 자원에 따라(다른 자원에 의존) 동작이 달라야 한다면 인스턴스를 생성할 때 생성자에게 필요한 자원을 넘겨주는 것이 좋습니다. 이 패턴을 응용해 생성자에게 자원 팩토리를 넘겨주는 방식이 있습니다.

public class SpellChecker {
    private final Lexicon dictionary;

    public SpellChecker(Lexicon dictionary) {
        this.dictionary = Objects.requireNonNull(dictionary);
    }
    
    public boolean isValid(String word) {
        return true;
    }
    
    public List<String> suggestions(String typo) {
        return new ArrayList<>();
    }
    
}

이때 넘겨지는 자원은 정확한 구현체가 아닌 인터페이스여야 합니다.

public interface Lexicon {
}

의존 객체 주입 핵심 정리

클래스가 내부적으로 하나 이상의 자원에 의존하고, 그 자원이 클래스 동작에 영향을 준다면 싱글턴과 정적 유틸리티 클래스는 사용하지 않습니다. 이 자원은 클래스가 직접 만들어서도 안 됩니다. 대신 필요한 자원을 생성자에게서 받도록 합시다.

댓글남기기