언어/Effective Java

이펙티브 자바 Item5 - 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라

now0204 2024. 5. 27. 15:54

 

사용하는 자원에 따라 동작이 달라지는 클래스는 정적 유틸리티 클래스나 싱글턴 방식이 적합하지 않다.

 

1. 자원 직접 주입 

 

대부분의 클래스는 여러 리소스에 의존한다. 책에서는 SpellChecker와 Dictionary를 예로 든다.

두 객체 사이에는 의존관계가 있다.

 

아래는 static 유틸리티를 잘못 사용한 예이다. - 이는 유연하지 않고 테스트가 어렵다.

public class SpellChecker {
	private static final Lexicon dictionary = ...; // 의존하는 리소스 (의존성)
	private SpellChecker() {} // 객체 생성 방지 

	public static boolean isValid(String word) { ... } 
	public static List<String> suggestions(String typo) { ... } 
}
  • 직접 자원을 명시하기 때문에, 테스트가 어렵다. 
  • 의존성을 바깥으로 분리하여 외부로부터 주입받도록 해야 한다. (의존 객체 주입 패턴) 

2. 의존 객체 주입 

 

의존 객체 주입은 유연성과 테스트 용이성을 높여준다.

 

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 null; } 
}
  • 불변을 보장하여 변경될 일이 없다. 여러 클라이언트가 의존 객체를 안심하고 공유할 수 있다.

2. 팩토리 메서드 패턴

  • 비슷한 변형으로 생성자에 자원 팩터리를 넘겨줄 수 있다. 
  • 자원 팩토리란 자원을 계속 찍어내는 객체를 말한다 (자바 8의 Supplier 인터페이스가 대표적이다)
@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get(); // T 타입 객체를 찍어낸다
}

 

public class LottoTicketGenerator {

    private final NumberGenerator numberGenerator;

    public LottoTicketGenerator(Supplier<? extends NumberGenerator> numberGenerator) {
        this.numberGenerator = numberGenerator.get();
    }
}

결론적으로 클래스가 내부적으로 하나 이상의 자원에 의존하고, 그 자원 클래스 동작에 영향을 주거나 받는다면 싱글톤이나 정적 유틸리티 클래스는 사용하지 않는 것이 좋다.

또한 해당 자원을 클래스에 직접 때려박아도 안된다. 

대신 필요한 자원을 생성자를 통해 (혹은 정적 팩토리, 빌더)에 넘겨주자 

의존 객체 주입은 클래스의 유연성, 재사용성, 테스트 용이성을 개선해준다. 

 


참고자료 

https://velog.io/@lychee/%EC%9D%B4%ED%8E%99%ED%8B%B0%EB%B8%8C-%EC%9E%90%EB%B0%94-%EC%95%84%EC%9D%B4%ED%85%9C-5.-%EC%9E%90%EC%9B%90%EC%9D%84-%EC%A7%81%EC%A0%91-%EB%AA%85%EC%8B%9C%ED%95%98%EC%A7%80-%EB%A7%90%EA%B3%A0-%EC%9D%98%EC%A1%B4-%EA%B0%9D%EC%B2%B4-%EC%A3%BC%EC%9E%85%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EB%9D%BC

 

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

사용하는 자원에 따라 동작이 달라지는 클래스에는 ~정적 유틸리티 클래스~나 ~싱글턴 방식~이 적합하지 않다.이 조건을 만족하는 간단한 패턴은,인스턴스를 생성할 때 생성자에 필요한 자원을

velog.io

https://javabom.tistory.com/73

 

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

많은 객체는 하나이상의 자원을 의존한다. 아래와같이 자동 LottoTicketGenerator 객체가 있다고 가정해보자. class LottoTicketGenerator{ private final NumberGenerator generator = new RandomNumberGenerator(); public LottoTicket

javabom.tistory.com