Notice
Recent Posts
Recent Comments
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Archives
Today
Total
관리 메뉴

DeFacto-Standard IT

SOLID (4) - 의존 역전 원칙, DIP 본문

Design Pattern/References

SOLID (4) - 의존 역전 원칙, DIP

defacto standard 2017. 10. 28. 19:07

의존 역전 원칙 (DIP, Dependency Inversion Principle)

객체 사이에 서로 도움을 주고받으면 의존 관계가 발생한다. 의존 역전 원칙은 그러한 의존 관계를 맺을 때의 가이드라인에 해당.


*DIP는 의존 관계를 맺을 때 변화하기 쉬운 것 또는 자주 변화하는 것 보다는 변화하기 어려운 것, 거의 변화가 없는 것에 의존하라는 원칙.


변하기 쉬운 것과 변하기 어려운 것은 어떻게 구분하는가.

정책, 전략과 같은 어떤 큰 흐름이나 개념 같은 추상적인 것은 변하기 어려운 것에 해당하고

구체적인 방식, 사물 등과 같은 것은 변하기 쉬운 것으로 구분하면 좋다.


아이가 장난감을 가지고 노는데 어떤 경우에는 로봇을, 어떤 경우에는 자동차를 가지고 놀 것이다.

이때 구체적인 장난감은 변하기 쉬운 것이고, 아이가 장난감을 가지고 노는 사실은 변하기 어려운 것이다.

장난감 클래스에 DIP를 적용한 예

 


객체지향 관점에서는 이와 같이 변하기 어려운 추상적인 것들을 표현하는 수단으로 추상 클래스와 인터페이스가 있다.

DIP를 만족하려면 어떤 클래스가 도움을 받을 때 구체적인 클래스보다는 인터페이스나 추상 클래스와 의존 관계를 맺도록 설계해야 한다.

DIP를 만족하는 설계는 변화에 유연한 시스템이 된다.


*인터페이스나 추상 클래스와 의존 관계를 맺도록 설계

인터페이스 = 변하지 않는 것

구체 클래스 = 변하기 쉬운 것


DIP를 만족하면 의존성 주입(dependency injection)이라는 기술로 변화를 쉽게 수용할 수 있는 코드를 작성할 수 있다.

의존성 주입이란 말 그대로 클래스 외부에서 외존되는 것을 대상 객체의 인스턴스 변수에 주입하는 기술이다. 의존성 주입을 이용하면

다음과 같이 대상 객체를 변경하지 않고도 외부에서 대상 객체의 외부 의존 객체를 바꿀 수 있다.


public class Kid {
private Toy toy;

public void setToy(Toy toy) {
this.toy = toy;
}

public void play() {
System.out.println(toy.toString());
}
}

Kid 클래스에서 setToy 메서드로 아이가 가지고 노는 장난감을 바꿀 수 있다.

만약 로봇 장난감을 가지고 높고 싶다면 다음 코드가 그 일을 해줄 것이다.

public class Robot extends Toy {
public String toString() {
return "Robot";
}
}
public class Main{
public static void main(String[] args) {
Toy t = new Robot();
Kid k = new Kid();
k.setToy(t);
k.play();
}
}

레고를 가지고 놀고 싶어진다면 다음 코드면 된다.

Kid, Toy, Robot 등 기존의 코드에 전혀 영향을 받지 않고도 장난감을 바꿀 수 있다.

public class Lego extends Toy {
public String toString() {
return "Lego";
}
}
public class Main{
public static void main(String[] args) {
Toy t = new Robot();
Kid k = new Kid();
k.setToy(t);
k.play();
}
}

*만약 Kid 클래스가 다음 클래스 다이어그램 처럼 Robot 클래스와 연관 관계를 맺는다면 어떤 일이 발생할까

public class Kid {
private Robot toy;

public void setToy(Robot toy) {
this.toy = toy;
}

public void play() {
System.out.println(toy.toString());
}
}
public class Main{
public static void main(String[] args) {
Robot t = new Robot();
Kid k = new Kid();
k.setToy(t);
k.play();
}
}

이런 경우 레고로 장난감의 종류를 변경하려면 기존의 Kid 클래스가 다음처럼 바뀌어야 한다.

public class Kid {
private Lego toy;

// 아이가 가지고 노는 장난감의 종류만큼 메서드가 존재해야 함
public void setToy(Lego toy) {
this.toy = toy;
}

public void play() {
System.out.println(toy.toString());
}
}


장난감을 바꿀 때마다 코드를 계속 바꿔야 한다. 즉, DIP의 위반이 OCP의 위반을 초래한다.

Comments