본문 바로가기
Java/Effective Java

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

by setung 2021. 12. 20.

SpellChecker라는 맞춤법을 검사하는 클래스가 있다. 이 클래스는 Lexicon이란 사전 클래스를 의존한다.

코드는 아래와 같다.

class SpellChecker {

    private static final Lexicon dictionary = new KoreanDictionary();

    public static boolean isValid(String word) {
        return true;
    }

    public static List<String> suggestions(String typo) {
        return new ArrayList<>();
    }

}

class KoreanDictionary implements Lexicon {

}

interface Lexicon {

}

코드에선 KoreanDictionary를 직접 생성해서 사용하고 있는데, 다른 사전으로 교체할 수 없다는 문제점이 있다. EnglishDictionary가 필요하다면 별도의 SpellChecker 클래스를 만들어야 한다.

 

 

그럼 Lexicon에 final 키워드를 빼고 setter 메서드를 통해 사전을 교체하도록 만들면 어떨까?

class SpellChecker {

    private static Lexicon dictionary;

    public static void setDictionary(Lexicon dictionary) {
        SpellChecker.dictionary = dictionary;
    }

    public static boolean isValid(String word) {
        return true;
    }

    public static List<String> suggestions(String typo) {
        return new ArrayList<>();
    }

}

이 방식은 멀티스레드 환경에서 사용할 수 없다.

 

 

책에서 설명하는 가장 좋은 방법은 인스턴스를 생성할 때 생성자에 필요한 자원을 넘겨주는 방식이다.

class SpellChecker {

    private final Lexicon dictionary;

    public SpellChecker(Lexicon dictionary) {
        this.dictionary = dictionary;
    }

    public boolean isValid(String word) {
        return true;
    }

    public List<String> suggestions(String typo) {
        return new ArrayList<>();
    }
}
public class Main {
    SpellChecker korSpellChecker = new SpellChecker(new KoreanDictionary());
    SpellChecker engSpellChecker = new SpellChecker(new EnglishDictionary());
}

의존 객체 주입 방식을 통해 클래스의 유연성, 재사용성, 테스트 용이성에 이점을 준다.

 

참고로 의존하는 객체수에 비례하여 코드가 복잡해질 수 있는데, Spring의 핵심 기술인 IOC/DI가 의존 객체 주입을 좀 더 편하게 사용하도록 지원을 해준다.

댓글