본문 바로가기

General

[오브젝트] 11장 합성과 유연한 설계

 

상속과 합성

 객체지향 프로그래밍에서의 코드 재사용 기법, 상속과 합성을 비교해보자.

클래스 상속 Class Inheritance 객체 합성 Object Composition
is-a 관계 has-a 관계
클래스간 정적인 관계 객체간 동적인 관계
부모 클래스와 자식 클래스를 연결해서
부모 클래스의 코드를 재사용
전체를 표현하는 객체가 부분을 표현하는 객체를 포함해서
부분 객체의 퍼블릭 인터페이스를 재사용
구현에 의존 인터페이스에 의존
white-box reuse black-box reuse

 

합성은 상속과 다르게 구현이 아닌 인터페이스에 의존하기 때문에 안정성과 유연성이라는 장점을 제공한다.

상속은 부모의 세부적인 구현에 자식을 강하게 결합시키기 때문에 코드 재사용을 하고 싶을 때 우아하게 사용할 수 있는 방법은 아니다. 상속에서 새로운 정책을 추가하기 위해서는 불필요할 정도로 많은 클래스를 추가해야했다. (인터페이스 상속이 아니라 구현 상속의 일 경우의 특징이다.)

반면, 합성을 이용한 설계는 단일 책임 원칙을 준수한다. 새로운 정책에 해당하는 클래스 하나만 추가하고, 원하는 대로 조합만하면 된다. 수정이 필요할 때도 하나의 클래스만 수정하면 된다. 따라서 합성, 즉 객체를 조합하고 사용하는 방식은 상속을 사용한 방식보다 더 일관적이고 예측가능하게 된다. 

 

 

상속을 합성으로

상속을 합성으로 바꾸는 방법은 다음과 같다. 자식 클래스에 선언된 상속 관계를 없애고, 자식 클래스의 인스턴스 변수로 부모 클래스의 인스턴스를 선언한다. 이렇게 되면 자식 클래스에서 필요로하는 오퍼레이션만 직접 정의해서 사용할 수 있다.

Java의 interface 사용하면, 아래의 remove처럼 구현 결합도는 제거하면서 퍼블릭 인터페이스는 그대로 상속 받을 게 할 수 있다. 이렇게 부모 인스턴스의 메서드에 그대로 전달만 하는 메서드를 포워딩 메서드(Forwarding Method)라고 한다.

public class IntstrumentedHashSet<E> implements Set<E> {
  private Set<E> set;
  
  public IntstrumentedHashSet(Set<E> set) {
    this.set = set;
  }

  @override public boolean remove(Object o) { return set.remove(o) };
}

 

 

 

 

 

 

출처: 오브젝트(코드로 이해하는 객체지향 설계) - 조영호 님