DI (Dependency Injection)

Concrete class 를 사용해서 객체를 생성하면, DIP 를 위반하고 결과적으로 OCP 를 위반하게 된다. 서비스 로케이터를 통해 의존 객체를 찾게 되면, 몇가지 단점이 발생한다. 이런 단점을 보완하기 위한 방법이 DI 이다. 필요한 객체를 직접 생성하거나 찾지 않고, 외부에서 넣어주는 방식이다. 사용할 객체를 전달받을 방법을 제공하면, DI를 적용하기 위한 준비가 끝난다.

생성자 방식

public calss JobCLI {
	private JobQueue jobQueue;

	public JobCLI(JobQueue jobQueue) {
		this.jobQueue = jobQueue;
	}

	public void interact() {
		this.jobQueue.addJob(jobData);
	}
}

설정 메서드 방식

public class Worker {
	private JobQueue jobQueue;
	private Transcoder transcoder;

	public void setJobQueue(JobQueue jobQueue) {
		this.jobQueue = jobQueue;
	}
	public void setTranscoder(Transcoder transcoder) {
		this.transcoder = transcoder;
	}

	public void run() {
		while(someRunningCondition) {
			JobData jobData = jobQueue.getJob();
			transcoder.transcode(jobData.getSource(), jobData.getTarget());
		}
	}
}

Main

public static void main(String[] args) {
	JobQueue jobQueue = new FileJobQueue();
	Transcoder transcoder = new FfmpegTranscoder();

	final Worker worker = new Worker();
	worker.setJobQueue(jobQueue);
	worker.setTranscoder(transcoder);

	Thread t = new Thread(new Runnable() {
		public void run() {
			worker.run();
		}
	});
	JobCLI cli = new JobCLI(jobQueue);
	cli.interact();
}

서비스 로케이터

서비스 로케이터는 앱에서 필요한 객체를 제공하는 책임을 가진다. 의존 대상이 되는 객체 별로 제공 메서드를 정의한다.

public class Worker {
	public void run() {
		ServiceLocator locator = ServiceLocator.getInstance();
		JobQueue jobQueue = locator.getJobQueue();
		Transcoder transcoder = locator.getTranscoder();
		...
	}
}

서비스 로케이터는 앱 영역의 객체에 직접 접근하기 때문에, 앱 영역에 위치한다. 메인 영역에서는 서비스 로케이터가 제공할 객체를 생성하고, 이 객체로 서비스 로케이터를 초기화한다.

public static void main(String[] args) {
	FileJobQueue jobQueue = new FileJobQueue();
	FfmpegTranscoder transcoder = new FfmpegTranscoder();

	ServiceLocator locator = new ServiceLocator(jobQueue, transcoder);
	ServiceLocator.load(locator);

	Worker worker = new Worker();
	...
	JobCLI jobCli = new JobCLI();
	jobCli.interact();
}

public class Worker {
	public void run() {
		ServiceLocator locator = ServiceLocator.getInstance();
		JobQueue jobQueue = locator.getJobQueue();
		Transcoder transcoder = locator.getTranscoder();
		...
	}
}

public class ServiceLocator {
	private JobQueue jobQueue;
	private Transcoder transcoder;

	public ServiceLocator(JobQueue jobQueue, Transcoder transcoder) {
		this.jobQueue = jobQueue;
		this.transcoder = transcoder;
	}

	public JobQueue getJobQueue() {
		return jobQueue;
	}

	public Transcoder getTranscoder() {
		return transcoder;
	}

	private static ServiceLocator instance;
	public static void load(ServiceLocator locator) {
		ServiceLocator.instance = locator;
	}
	public static ServiceLocator getInstance() {
		return instance;
	}
}

단점