Sam Story

JAVA - 의존 역전 원칙 본문

JAVA

JAVA - 의존 역전 원칙

Sam H 2024. 10. 20. 18:25

오늘은 SOLID 원칙의 마지막 원칙인 의존 역전 원칙에 대해 포스팅 해보도록 하겠다.

 

SOLID 원칙에 관한 내용은 아래 포스팅 참고

 

https://samtistory.tistory.com/49

 

객체지향 프로그래밍 SOLID 원칙

지난번 포스팅 했던 객체지향 프로그래밍에 이어서객체지향 프로그래밍의 5가지 원칙 SOLID 원칙에 대해 포스팅 하려한다.  SOLID 원칙 이란? SOLID란 객체 지향 프로그래밍을 하면서 지켜야하

samtistory.tistory.com

 

5. 의존 역전 원칙(DIP)

 

의존 역전 원칙은 어떤 Class를 참조해서 사용해야하는 상황이 생긴다면,

그 Class를 직접 참조하는 것이 아니라

그 대상의 상위요소 (추상 클래스 or 인터페이스)로 참조 하라는 원칙이다.

 

쉽게 이야기하면 구현 클래스에 의존하는것이 아닌 인터페이스에 의존하라는 뜻

 

의존 관계를 맺을 때 변화하기 쉬운 것 또는 자주 변화하는 것보다는

변화하기 어려운것 혹은 거의 변화가 없는 것에 의존하라는 것이다.

 

 

객체들이 서로 정보를 주고 받을 때는 의존 관계가 형성되는데,

클라이언트(사용자)가 상속 관계로 이루어진 특정 모듈을 가져다 사용할때,

하위 모듈을 직접 인스턴스를 가져다 쓰지 말라는 뜻이다.

 

왜냐하면 그렇게 할 경우, 하위 모듈의 구체적인 내용에 클라이언트가 의존하게 되어

하위 모듈에 변화가 있을 때마다 클라이언트나 모듈의 코드를 자주 수정해야 되기 때문이다.

 

 

예제를 통해 의존 역전 원칙에 대해 좀 더 쉽게 이해해보자.

 

 

동물계에는 많은 동물들이 존재한다.
다음과 같이 육지동물,해양동물,하늘동물 클래스가 있다고 가정하자.

 

LandAnimals class , SeaAnimals class , SkyAnimals class

// 육지동물 클래스
public class LandAnimals {

    String name;
    String type;

    LandAnimals(String name,String type) {

        this.name = name;
        this.type = type;

    }

    // 육지동물의 정보를 리턴하는 메서드
    String getAnimalInfo() {

        return type + " : " + name;

    }

}

// 해양동물 클래스
public class SeaAnimals {

    // ... 위 내용과 동일
    
}

// 하늘동물 클래스
public class SkyAnimals {

    // ... 위 내용과 동일

}

 

 

그리고 이러한 동물들을 사냥하는 Hunter클래스가 있다.

이 Hunter 클래스는 인스턴스화 할때 동물의 이름과 동물의 타입을 입력값으로 받아 초기화 한다.

육지동물에도 다양한 타입의 동물들이 올 수 있기 때문에

Hunter 클래스 내에 필드 변수로서 육지동물 클래스 타입의 변수를 저장해놓고
huntAnimal() 메서드를 수행하면 LandAnimal 클래스의 메서드가 실행되어 사냥을 하는 형태이다.

 

 

Hunter class

public class Hunter {

    LandAnimals animal;

    String huntAnimal(LandAnimals landAnimals) {

        this.animal = landAnimals;
        return animal.getAnimalInfo() + "을 사냥 합니다";

    }

}

 

 

하지만 동물은 육지동물만 있는 게 아니다.

위에서 살펴봤듯이 육지동물, 해양동물 , 하늘동물 타입의 여러 동물들을 사냥하게 하려면,

아예 Hunter class의 클래스 필드 변수 타입을 교체해줘야 한다.

 

그렇기 때문에 위 코드의 문제는 이미 완전하게 구현된 하위 모듈을 의존하고 있다는 점이다.

 

 

그렇다면 의존 역전 원칙을 지키려면 어떻게 해야하는지 그림을 통해 알아보자.

 

먼저 모든 동물들을 포함하는 동물이라는 상위 인터페이스를 구현하고,

각 하위 클래스에서 이를 implements 해준다.

또한, Hunter class의 메서드는 동물 인터페이스를 사용하는 상위 객체에 의존하도록 작성해준다.

 

 

코드를 통해서 보도록 하자.

 

Animal Interface , LandAnimals class , SeaAnimals class , SkyAnimals class

// Animal Interface
public interface Animal {

    String getAnimalInfo();

}

// 육지동물 class
public class LandAnimals implements Animal{

    String name;
    String type;

    LandAnimals(String name,String type) {

        this.name = name;
        this.type = type;

    }

    // 동물의 정보를 리턴하는 메서드 오버라이드 하여 작성
    @Override
    public String getAnimalInfo() {
    
        return type + " : " + name;
        
    }
    
}

// 해양동물 class
public class SeaAnimals implements Animal{

    String name;
    String type;

    SeaAnimals(String name,String type) {

        this.name = name;
        this.type = type;

    }

    // 동물 정보 리턴하는 메서드
    @Override
    public String getAnimalInfo() {

        return type + " : " + name;

    }

}

// 하늘동물 class
public class SkyAnimals implements Animal{

    String name;
    String type;

    SkyAnimals(String name,String type) {

        this.name = name;
        this.type = type;

    }

    // 동물 정보 리턴하는 메서드
    @Override
    public String getAnimalInfo() {

        return type + " : " + name;

    }

}

 

위 그림처럼 Animal 이라는 상위 Interface를 구현하고 각 동물 class들에 implements 해준다.

 

이렇게 육지동물 , 해양동물 , 하늘동물 class에 상위 모듈인 Animal Interface를 이용해 Hunter class를 수정해보자.

 

 

Hunter class

public class Hunter {

    Animal animal; // 구현한 상위 Interface

    String huntAnimal(Animal animal) {

        this.animal = animal;
        return animal.getAnimalInfo() + "을 사냥 합니다";

    }
    
    String changeTargetAnimal(Animal animal) {

        this.animal = animal;
        return animal.getAnimalInfo() + "으로 타겟을 변경합니다.";

    }
    
}

 

위 내용처럼 상위 Interface를 implements 하고 있는 class를 통해 구현하게 되면

 

육지동물 , 해양동물 , 하늘동물 상관없이 매개변수로 받을 수 있는 메서드를 작성할 수 있고

동물의 변경에 따라 huntAnimal() 메서드를 수정할 필요가 없어진다.

 

그리고 또다른 동물들을 확장도 얼마든지 할 수 있으므 개방 폐쇄 원칙도 지켜지게 되는것이다.

 

 

이렇게 SOLID 원칙 5가지에 대해 포스팅 해보았는데

이러한 내용들을 공부하다 느낀것은 각 원칙들이 서로 유기적으로 연결되어 있다는 것이다.

 

 

그렇기 때문에 설계단계에 있어서 항상 이러한 원칙들을 고려하여 설계를 해야한다.

'JAVA' 카테고리의 다른 글

JAVA - 인터페이스 분리 원칙  (1) 2024.10.16
JAVA - 리스코프 치환 원칙  (0) 2024.10.15
JAVA - 개방 폐쇄 원칙  (0) 2024.10.14
JAVA - 단일 책임의 원칙  (1) 2024.10.12
JAVA - 2~36진수 기수변환  (0) 2024.09.29