강한 결합과 느슨한 결합

한상우·2022년 10월 3일
0

java

목록 보기
5/16

Q. 강한 결합과 느슨한 결합이 무엇인지 설명


들어가기에 앞서 모듈과 모듈화에 대해 먼저 알아보자
모듈화란 소프트웨어를 기능별로 나누는 것을 의미한다
각 기능별로 나누어진 결과를 모듈이라고 한다

좋은 모듈화는 목적에 맞는 기능만으로 모듈을 나누어 다른 모듈과 적게 연관되는 것을 의미한다 ( = 독립성이 강한 모듈 )

이러한 모듈의 독립성은 모듈의 결합도와 응집도로 측정한다
그리고, 모듈의 독립성을 높이기 위해서는 낮은 결합도와 높은 응집도를 요구한다

  • 결합도: 모듈간 상호 의존 정도
  • 응집도: 모듈 내부 요소들의 서로 관련되어 있는 정도

결합도란

서로 다른 모듈간 상호 의존하는 정도

강한 결합이란

어떠한 객체가 다른 객체에 강한 의존성을 가지고 있는 것

... 코드로 공부할게요

상황) 사람 클래스와 Gv80 클래스가 있다. Gv80은 drive 메소드가 있고 사람 클래스는 맴버 변수로 Gv80을 가지고 있으며 startDrive 메소드를 통해 맴버 변수의 drive 메소드를 호출할 수 있다

class Person {

    private Gv80 gv80;

    public Person() {
        this.gv80 = new Gv80();
    }

    public void startDrive() {
        gv80.drive();
    }

}

class Gv80 {

    public void drive() {
        System.out.println("Gv80 부릉부릉~");
    }
}

위 코드의 문제점은?

  • Gv80 클래스가 없으면 Person 클래스를 정의할 수 없다
  • Gv80 클래스를 바꾸게 되면 코드 수정이 많이 이루어짐

이렇게, 강한 의존성을 지니게 되면 강한 결합이라고 하고 이는 유지 보수 측면에서 좋지 않다

느슨한 결합 (약한 결합)

이를 해결해줄 수 있는 것이 인터페이스 이다.

interface Car {
    void drive();
}

class Person {

    private Car car;

    public Person(Car car) {
        this.car = car;
    }

    public void startDrive() {
        car.drive();
    }

}

class Gv80 implements Car{

    @Override
    public void drive() {
        System.out.println("Gv80 부릉부릉~");
    }
}

Car 인터페이스를 만들어 drive 추상 메소드를 선언
Gv80 클래스에서는 이를 구현한다.

이러면 Gv80 객체는 Car 타입에 대입될 수 있으므로 Person 클래스에서 맴버변수 타입을 Car로 둘 수 있는 것이다.
생성자를 통해 객체를 받아 맴버변수에 대입만 하면 되므로
Person 클래스 내부에 변경이 일어나지 않게 된다

추가

이처럼 요구 사항이 새로 추가되거나, 바뀌어도 변경이 전파되지 않도록 막는 것이 객체 지향의 장점이라 할 수 있다.
이 방법 중 하나가 캡슐화라고 할 수 있다
캡슐화란 데이터(속성)와 함수(메소드)를 하나로 묶는 작업
즉, 클래스 안에다가 데이터와 데이터를 처리하는 함수를 묶어 외부에 감추는 것이다

캡슐화

public class App {

    public static void main(String[] args) {

        Bag bag = new Bag(10000);
        double discountPrice = bag.discount();
    }
}

class Bag {

    private int price;

    public Bag(int price) {
        this.price = price;
    }

    public double discount() {
        return price / 2;
    }
}

위와 같은 코드가 있다 해보자,
Bag 클래스는 price라는 내부 데이터를 가지고 있고, 데이터를 처리하는 discount라는 메소드도 가지고 있다.
메인 메소드 입장에서는 discount 메소드를 쓸 수 있지만 내부 동작을 모른다. 캡슐화의 정의를 만족한다.

캡슐화를 안지키는 경우는 아래와 같다

public class App {

    public static void main(String[] args) {

        Bag bag = new Bag(10000);
        double discountPrice = bag.getPrice() / 2;
    }
}

class Bag {

    private int price;

    public Bag(int price) {
        this.price = price;
    }

    public int getPrice() {
        return price;
    }
}

같은 결과를 도출하겠지만, 문제점이 있다.
1. discounPrice 값을 얻기 위한 중복 코드가 발생한다
2. 할인율이 바뀌게 된다면 코드 수정이 여러 군데 발생하게 된다

위와 같은 문제점들은 캡슐화를 진행함으로써 단순히 해결된다.

즉, 캡슐화는 외부에서 알 필요가 없는 부분을 감춤으로써 대상을 단순화하는 것이고 인터페이스와 구현의 영역을 분리하여 변경의 영향을 통제할 수 있다

profile
안녕하세요 ^^

0개의 댓글