프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것
개발자 입장에서는 구현 객체가 프로그램의 제어 흐름을 스스로 제어하는 것이 자연스러운 흐름이다.
public class ServiceImpl implements Service {
private final Repository repository = new A_Repository();
private final Policy policy = new A_Policy();
@Override
...
}
위 코드가 DIP 원칙을 지키기 위해서, 아래와 같이 위 코드를 수정하고 설정 클래스(AppConfig)를 추가해야 한다.
public class AppConfig {
public Service service() {
return new ServiceImpl(new A_Repository(), new A_Policy());
}
}
public class ServiceImpl implements Service {
private final Repository repository;
private final Policy policy;
public ServiceImpl(Repository repository, Policy policy) {
this.repository = repository;
this.policy = policy;
}
@Override
...
}
IoC 설명을 마무리 하기위해 DI에 대해서 간단히 설명하면, DI는 실행 시점에 필요한 객체를 직접 생성하는 것이 아니라 외부로 부터 필요한 객체를 받아서 사용하는 것이다.
실행 시점에 외부에서 실제 구현 객체를 생성하고 이를 필요로 할 클래스에게 전달하여 두 클래스의 실제 의존관계가 연결되는 것
public class ServiceImpl implements Service {
private final Repository repository;
private final Policy policy;
public ServiceImpl(Repository repository, Policy policy) {
this.repository = repository;
this.policy = policy;
}
@Override
...
}
위 코드를 보면, ServiceImpl 클래스는 Repository와 Policy를 의존한다고 할 수 있다. 하지만 실제 어떤 구현 객체가 ServiceImpl 클래스에 주입될지는 알 수 없다.
public class AppConfig {
public Service service() {
return new ServiceImpl(new A_Repository(), new A_Policy());
}
}
ServiceImp 클래스에 Repository와 Policy으로 A_Repository와 A_Policy를 주입한다는 것은 어플리케이션 실행 시점에 알 수 있다.