Skip to content

SOLID: Dependency Inversion Principle (의존 역전 원칙)

VG edited this page Dec 20, 2020 · 23 revisions

DIP (의존[1] 역전 원칙)

  1. 상위수준에 위치한 개체는 하위수준에 위치한 개체에 의존해서는 안된다. 상위개체, 하위개체 모두 추상화에 의존해야 한다.
  2. 추상화는 세부 사항에 의존해서는 안된다. 세부사항이 추상화에 의존해야 한다.

위반 예제

아이와 장난감Java

장난감을 가지고 노는 아이를 만들어보겠다.

해당 다이어그램대로 코드를 짜보겠다.

public class Robot{
    public String toString() {
        return "로봇을 가지고 놉니다.";
    }
}
public class Car{...}
public class Lego{...}
public class Kid {
    private Robot robot;
    private Car car;
    private Lego lego;

    public Kid(Robot robot, Car car, Lego lego)
    {
        this.robot = robot;
        this.car = car;
        this.lego = lego;
    }

    public void playRobot() {
        System.out.println(robot.toString());
    }
    public void playCar() {
        System.out.println(car.toString());
    }
    public void playLego() {
        System.out.println(lego.toString());
    }
}
public class Main{
    public static void main(String[] args) {

        Kid kid = new Kid(new Robot(), new Car(), new Lego());

        kid.playRobot();

        kid.playCar();
    }
}

상위수준의 개체인 Kid클래스가 하위수준의 개체인 장난감클래스들에게 의존하고있다.🛑DIP위반

이렇게 되면, 3장난감 말고도 비행기, 기차 등 새로운 장난감이 들어올 때마다, 매번 Kid 클래스에 새로운 장난감을 선언하고, 생성자 매개변수 추가, 초기화 코드 추가까지 해주어야 한다.🛑OCP위반

그렇다면 어떻게 고쳐야 할까?

public class Robot extends Toy {
    public String toString() {
        return "로봇을 가지고 놉니다.";
    }
}
public class Car extends Toy{...}
public class Lego extends Toy{...}
public class Kid {
    private Toy toy;

    // setter를 통해, 의존성 주입을 실천하였다.
    public void setToy(Toy toy) {
        this.toy = toy;
    }

    public void play() {
        System.out.println(toy.toString());
    }
}
public class Main{
    public static void main(String[] args) {
        Toy t = new Robot();
        Kid k = new Kid();
        k.setToy(t);
        k.play();
        //로봇을 가지고 놉니다.

        t = new Car();
        k.setToy(t);
        k.play();
        //자동차를 가지고 놉니다.
    }
}

Toy이라는 추상 클래스 또는 인터페이스를 만들어, 장난감에 해당하는 클래스들은 Toy를 상속 받도록 만들었다.
그리고 Kid클래스는 Toy라는 추상 개체에게 의존하게 된다.
또한, Kid객체가 생성됐을 때만 초기화할 수 있었던 장난감들을, setter(.setToy(Toy toy);)메소드를 이용해 언제, 어디서든 의존성 주입[2]을 할 수 있다.

이로써, 새로운 장난감이 생겨도 유연하게 대처할 수 있게되었다.


각주

[1]의존이란?[↻]

누구에게 의존한다. = 스스로 할 수 없다.
∴ 누군가가 일을 대신 해주어야 한다.

예제

public class PC {
    private Game game;
    private Internet internet;

    public void setGame(Game game) {
        this.game = game ;
    }
    public void setInternet(Internet internet) {
        this.internet = internet;
    }

    public void playGame() {
        game.play();
    }
    public void surfInternet() {
        internet.surf();
    }
}

해당 예제의 경우 PC는 Internet과 Game에 의존하고 있다.

[2]의존성 주입(Dependency Injection)이란?[↻]

하나의 객체가 다른 객체의 의존성을 제공하는 테크닉이다.
"의존성"은 예를 들어 서비스로 사용할 수 있는 객체이다.
클라이언트가 어떤 서비스를 사용할 것인지 지정하는 대신, 클라이언트에게 무슨 서비스를 사용할 것인지를 말해주는 것이다. 출처: 위키백과

쉽게말해
클래스가 어떤 개체에 의존할 것인지 직접 지정하는 것이 아닌,
클래스에게 어떤 개체를 의존할 것인지 말해주는 것이다.

Clone this wiki locally