SOIEU.TAGSABOUT

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

핵심

  1. 필드에 자원을 미리 설정하지 않는다
    • 객체 내부에서 자원을 직접 생성하거나 고정된 자원에 의존하지 않는다.
    • 대신, 객체 생성 시 필요한 자원을 생성자를 통해 외부에서 전달받는다.
  2. 자원의 개수와 종류에 제한이 없다
    • 생성자를 통해 필요한 자원을 얼마든지 넘겨줄 수 있다.
    • 예: 데이터베이스 커넥션, 파일 핸들러, 네트워크 클라이언트 등.
  3. 불변성을 보장하여 안심하고 공유 가능
    • 생성 시 전달받은 자원을 변경하지 않도록 설계하여 불변 객체로 만든다.
    • 여러 클라이언트가 동시에 객체를 사용하더라도 안정성을 유지할 수 있다.
  4. 자원 팩터리(팩터리 메서드)를 사용 가능
    • 자원을 생성하는 팩터리 메서드(또는 팩터리 클래스)를 생성자에 전달하여, 유연하게 자원을 생성하거나 주입할 수 있다.

장점

  • 테스트 용이성: 자원을 외부에서 주입받으므로, 테스트 시 가짜(Mock) 자원을 주입하여 쉽게 테스트할 수 있다.
  • 재사용성 증가: 객체 내부에서 자원을 직접 생성하지 않기 때문에, 다양한 자원과 함께 재사용 가능하다.
  • 유연성 강화: 자원의 생성과 사용을 분리하여, 자원을 주입받는 객체는 어떤 자원이 주입되었는지 몰라도 동작할 수 있다.

구현 예시 - 텍스트를 출력하는 클래스

  • 파일에 데이터를 출력하거나, 콘솔에 데이터를 출력할 수 있는 **출력 도구(PrintStream)**를 주입받는다.
  • 내부에서 자원을 생성하지 않으므로, 자원을 변경하려면 생성자에 새로운 자원을 주입하면 된다.
import java.io.PrintStream;

public class TextPrinter {
    private final PrintStream output;

    // 생성자를 통해 자원을 주입받음
    public TextPrinter(PrintStream output) {
        this.output = output;
    }

    public void print(String message) {
        output.println(message);
    }
}

import java.io.FileOutputStream;
import java.io.PrintStream;

public class Main {
    public static void main(String[] args) throws Exception {
        // 콘솔 출력에 사용
        TextPrinter consolePrinter = new TextPrinter(System.out);
        consolePrinter.print("Printing to console");

        // 파일 출력에 사용
        try (PrintStream fileStream = new PrintStream(new FileOutputStream("output.txt"))) {
            TextPrinter filePrinter = new TextPrinter(fileStream);
            filePrinter.print("Printing to file");
        }
    }
}