Dependency Injection을 다루기 전에 왜 DI를 해야하는지 알아야한다.
명시적 의존성이란 클라이언트 객체로 하여금 해당 객체의 의존성을 명시적으로 보여줘야한다는 의미이다.
즉 의존성을 다음과 같이 꽁꽁 숨겨두지 말라는 소리이다.
class Computer{
private USB usb
Computer(){
this.usb = new Moniter();
}
}
또한 new를 사용하지 말라는 의미이기도 하다.
이렇게 숨겨진 의존성이 있으면 강하게 결합된다.
OCP에 따라 수정에 닫혀있으려면 저 new Moniter
를 new Printer
로 바꾸는 일은 없어야한다.
때문에 다음 3가지 방법과 같이 의존성을 명시적으로 퍼블릭 인터페이스에 노출시켜야 (Computer 생성자) 수정에 닫혀있지만 확장에는 열려있을 수 있다.
명시적 의존성을 DI로 만든다.
class Computer{
private USB usb
Computer(USB usb){
this.usb = usb;
}
}
생성자로 의존성을 주입하면 객체가 처음부터 의존성을 달고 있어서 NullPointerException이 일어나지 않지만 생명주기 동안 의존성을 갈아치울 수 없다.
class Computer{
private USB usb
public void setUSB(USB usb){
this.usb = usb;
}
}
Setter로 의존성을 주입하면 객체 생명주기 동안 의존성을 변경할 수 있지만 의존성을 set 하지 않았을 때 의존성에 접근하면 NullPointerException이 일어난다.
따라서 생성자와 setter를 동시에 사용하는 방법이 권장된다.
class Computer{
private USB usb
Computer(USB usb){
this.usb = usb;
}
public void setUSB(USB usb){
this.usb = usb;
}
}
class Computer{
private String modelName;
public void printComputerModel(USB usb){
usb.print(modelName);
}
}
메서드 인자를 통해서 의존성을 주입할 수 있다. 의존성이 함수 동작 시에만 존재하기 때문에 의존성의 사용처가 한 두개일 경우 인자를 통해 의존성을 주입한다.