Chapter 011 : 합성과 유연한 설계

2025. 5. 25. 02:00
반응형
Garbage Collection Guide

합성은..

합성은 상속과 함께 코드 재사용을 피하기 위한 방법 중 하나이다.
앞서 알아본 상속의 문제점을 생각해보면 상속은 부모 클래스에 대해서 자세히
알고 있어야하며 이로 인해 부모 클래스와 자식간의 결합도가 높아진다.
우선 상속의 단점들을 상기시켜 합성의 장점을 알아보자


불필요한 인터페이스 상속 문제 해결

앞에서 알아본 Java 에서 Stack 객체는 Vector 라는 구조를
상속 받아 만들었고 불필요한 상속으로 인해 Stack 에서 자료를 추가하는
push() 메서드와 Vector의 add() 메서드를 사용하는 문제가 발생하였다.
이를 합성에서는 다음과 같이 사용한다.

public class Stack {
 private Vector elements = new Vector();
 
 public E push(E item) {
	 elements.addElements(item);
 }
 
 public E pop(){
  if(elements.isEmpty()) {
    throw new EmptyStackException();
  }
  return elements.remove(elements.size() - 1 );
 }
}

이렇게 사용함으로 써 Vector 의 add 메서드 같이 불필요한
오퍼레이션이 포함되지 않는다.


메서드 오버라이딩 오작동

메서드 오버라이딩 오작동 문제는 자식 클래스가 특정 메서드에서
부모 클래스의 메서드를 사용할 때 발생하는 문제이다.
합성을 통해서 이 문제를 어떻게 해결할까?
인터페이스를 활용하여문제를 해결한다.

public class InstrumentsHashSet implements Set{
 
}

부모 클래스와 자식 클래스 동시 수정

해당 문제는 로직상 문제는 없으나 요구사항이 변경 된 경우
비지니스적으로 문제가 발생하였다. 하지만 이 상속 문제를 합성으로
해결한다고 해결 될 문제가 아니다. 그렇지만 내부적인 파급 효과를 상속보다 줄일 수 있다.

결국 합성으로 코드 재사용을 줄이는 것이 더욱 이점이 된다는 결론에 다다른다.

상속으로 코드 중복을 줄이면 생기는 문제점

이번 챕터에서 책의 상당 부분을 여기서 코드 중복으로 상속을 사용하면
안되는 이유에 대해서 길게 써줬는데.. 간단히 읽은 내용을 용약하자면

  1. 중복되는 문제를 부모 클래스의 추상 메서드에 추가하면, 오버라이딩 하는 메서드 수가 늘어난다.
  2. 부분적으로 비슷한 클래스를 많이 생성한다. ( 객체 지향 언어는 기본적으로 단일 상속만 지원 )
  3. 이로 인해 계층이 너무 복잡해진다.

이러한 문제점을 해결하는 것 역시 합성이다.
합성은 상속과 다르게 동적으로 관계를 변경할 수 있다. 그리고 과도하게
특정 클래스에 대해 의존적이지 않게 된다.

문제점을 합성으로 해결하기


1. 공통되는 오퍼레이션을 모아 Interface 로 정의하기

public interface RatePolicy {
 Money calculateFee(Phone phone);
}

2. 해당 인터페이스 구현체들을 생성한다.

public abstract class BasicRatePolicy implements RatePolicy{
...
}

public class RegularPolicy extends BasicRatePolicy{
...
}

public class NightlyDiscountPolicy extends BasicRatePolicy{
...
}

3. 합성할 클래스에서 인터페이스를 합성

public class Phone {
 private RatePolicy ratePolicy;
 ...
}

이로 인한 장점에 대해서 알아보자면


캡슐화가 완전해 진다.

이 말이 좀 애매할 수 있는데, 내가 이해한것을 설명하자면

public class Phone {
 private RatePolicy ratePolicy;
 ...
}

이렇게 합성한 경우 RatePolicy 를 상속받거나 구현한 정책들간의
비지니스 로직이 변경되거나 추가된다고 해도 합성을 수행한 클래스 ( Phone ) 의 입장에서는
그저 RatePolicy 를 상속받거나 구현한 클래스만 받으면 된다.

믹스인

객체 생성 시 크드 일부를
클래스 안에 섞어 넣어 재사용하는 방법 이다.
이로 인해 다중 상속 없이 조합하는데 사용한다.

얼핏 보면 합성방식과 비슷해 보이는데, 차이점을 보면


합성

public class Wing {
    public void flap() {
        System.out.println("날개를 퍼덕입니다!");
    }
}
public class Bird {
    private Wing wing; // 합성: Wing 객체를 내부에 포함

    public Bird() {
        this.wing = new Wing();
    }

    public void move() {
        System.out.println("움직입니다.");
        wing.flap(); // 기능을 위임
    }
}

이처럼 합성은 기능을 가진 객체 자체를 구성 요소로 추가한다.


믹스인

public class FlyableMixin {
    public void fly() {
        System.out.println("날아갑니다!");
    }
}
public class Bird {
    private FlyableMixin flyable = new FlyableMixin();

    public void move() {
        System.out.println("움직입니다.");
        flyable.fly(); // mixin 사용
    }
}

이와 달리 믹스인은 클래스 내부에서 메서드를 가진 객체를
정의하고 해당 객체의 메서드를 사용한다.

즉, 합성은 외부로 부터 합성에 필요한 객체를 부여받지만
믹스인은 스스로 필요한 객체를 정의하여 사용한다.

✅ 마무리 정리

상속은 코드 재사용을 위한 고전적인 방법이지만
잘못 사용하면 높은 결합도와 유연성 부족이라는 문제를 가진다.

이에 대한 대안으로 합성과 믹스인이 존재하며,
상속의 단점을 피하면서도 코드 재사용과 유연성 을 확보할 수 있다.


합성

기능을 가진 객체를 외부에서 주입받아 내부 구성 요소로 사용하는 방식
의존성을 낮추고 유연한 설계를 가능


믹스인

공통 기능을 클래스 내부에 직접 정의하여 섞어 쓰는 방식
코드 재사용을 간결하게 만들고 다중 상속 없이 기능을 조합할 수 있게 한다

결론적으로, 복잡한 상속 계층보다는 합성과 믹스인 같은 조립 가능한 설계 방식을 통해,
변화에 강하고 유지보수가 쉬운 객체지향 시스템을 만드는 것이 좋다.

반응형

'IT 서적 > Object' 카테고리의 다른 글

상속과 중복 코드 : 오브젝트 Chapter 010  (0) 2025.05.17

BELATED ARTICLES

more