public class CPU { }
public calss Computer{
private CPU cpu;
public Computer(){
cpu = new CPU();
}
}
public class Computer{
private CPU cpu;
public void setCPU(CPU cpu){
this.cpu = cpu;
}
}
위 코드에서 봤듯이 Computer 는 CPU 라는 한 가지 타입에 의존을 하고있다
하지만 사용자가 다른 타입의 CPU를 사용하는 것을 원할 수 있다
예를 들어 A회사의 CPU로 컴퓨터를 만들고 싶다면 기존 CPU 클래스명을 CPU_A로 변경하거나 새로 만들어야 한다
하나의 클래스를 변경하거나 새로 만드는 것은 어렵지 않지만 CPU 클래스를 의존하던 Computer 클래스도 같이 변경을 해줘야하는 문제점이 생긴다
public class Computer{
private CPU_A cpu; // A로 변경됨
public Computer(){
cpu = new CPU_A(); // 이 부분 역시 변경됨
}
}
하나의 클래스를 변경함으로써 다른 의존 관계까지 변경 사항이 전이되는 모습을 볼 수 있다
이를 해결하기 위해 Computer가 의존하는 CPU를 인터페이스 형태로 만들어본다
CPU를 구현한 어떤 클래스 간에 Computer의 CPU로써 기능할 수 있게 만드는 것이다
public interface CPU {...}
public class CPU_A implements CPU {...}
public class Computer{
private CPU cpu;
public Computer(){
cpu = new CPU_A();
// cpu = new CPU_B();
}
}
하지만 아직 문제점이 남아있다. 만약 B CPU를 사용해야 한다면 다시 Computer 클래스를 변경해야 한다.
public class Computer{
private CPU cpu;
public Computer(){}
public Computer(CPU cpu){
this.cpu = cpu;
}
public void setCPU(CPU cpu){
this.cpu = cpu;
}
}
public static void main(String[] args){
CPU cpu = new CPU_B;
Computer cmp1 = new Computer(cpu);
// Or
Computer cmp2 = new Computer();
cmp2.setCPU(cpu);
}
Computer 클래스의 생성자에서 CPU 객체를 만들지 않고, 외부로부터 CPU 객체를 생성한 뒤 Computer 생성자 또는 메서드의 매개변수로 객체를 제공한다.
기존에는 Computer가 CPU 객체를 생성하고 관리했으나 개선된 코드에서는 CPU 객체의 생성 및 관리를 외부에 위임했다.
이를 제어의 역전이라고 한다.
제어의 역전을 통해 결합도를 약하게 했고, Computer는 이제 CPU의 변경 사항에 의해 내부 필드나 메서드 매개 변수를 변경하지 않아도 된다.