11 합성과 유연한 설계

 

들어가며

 

상속은 부모 클래스의 정의 대부분을 자식 클래스가 물려받을 수 있어 기존 코드를 쉽게 확장할 수 있다. 그러나 상속을 활용하기 위해서는 부모클래스의 내부 구현에 대해 상세히 알아야 하기 때문에 부모-자식 간 결합도가 높아져 상속은 코드를 재사용할 수 있는 쉽고 간단한 방법일지라도 결코 우아한 방법은 아니다.

 

이에 반해 합성은 합성 내부에 포함되는 객체의 내부 구현이 아닌 퍼블릭 인터페이스에 의존하기 때문에 결합도가 낮고 합성으로 포함된 내부객체의 변경의 영향을 최소화해 더 안정적인 코드를 얻을 수 있다.

 

 

 

02 상속으로 인한 조합의 폭발적인 증가

 

상속으로 인해 결합도가 높아지면 코드를 수정하는 데 필요한 작업의 양이 과도하게 늘어나는 경향이 있다.

 

그림을 통해 살펴보자.

 

 

앞선 장에서 나왔던 기본정책에서 추가로 부가정책이란 새로운 정책이 추가되었다고 가정하자.

기본 정책은 부가 정책들과 조합될 수 있으며

기본정책은 복수개의 부가 정책과 조합이가능하며
기본정책에 조합되는 부가 정책 적용 순서도 다르게 조합할 수 있다.

 

그림으로 표현하면 이렇다.

 

 

앞장에서 언급되었던 Phone, RegularPhone, NightlyDiscountPhoned 들의 상속 구조에서 새로운 부가정책의 요구사항이 추가 되었기 때문에 부가 정책이 적용된 상속 계층도 함께 살펴보자.

 

 

 

여기서 새로운 부가 정책인 '약정 할인 정책'이 추가된다면 어떻게 될까?

 

 

 

고작 부가정책 하나를 추가했음에도 불구하고 5개의 클래스를 생성해야하며 새로운 기본, 부가 정책이 추가될 수록 기하급수적으로 늘어날것이다.

 

이처럼 상속의 남용으로 하나의 기능을 추가하기 위해 필요이상으로 많은 수의 클래스를 추가해야하는 경우를 가리켜 클래스 폭발(class explosion) 문제라고 부른다. 자식클래스가 부모 클래스의 구현에 강하게 결합되도록 강요하는 상속의 근복적인 한계 때문에 발생하는 문제로 볼 수 있다.

 

 

 

03 합성 관계로 변경하기

 

합성을 사용하면 구현 시점에 정책들의 관계를 고정시킬 필요가 없으며 실행 시점에 정책들의 관계를 유연하게 변경할 수 있게 된다. 

 

 

 

Phone 내부에 RatePolicy에 대한 참조자가 포함돼 있으며 이것 바로 합성이다. 컴파일 타임에 의존성이 결정되는 상속과 달리 런타임에 의존성이 결정되어 결합도가 낮아졌으며 새로운 정책이 추가되면 단순히 클래스 '하나'만 추가 하면 된다.

 

아래는 '고정 요금제'가 추가된 모습이다.

 

 


객체 합성이 클래스 상속보다 더 좋은 방법이다

 

상속이 구현을 재사용하는데 비해 합성은 객체의 인터페이스를 재사용한다.

Phone은 RatePolicy 추상 인터페이스를 구현한 객체를 갈아끼우며 런타임에 원하는 의존성을 선택할 수 있어 전체적인 구조의 결합도가 낮아질 수 있다.

 

 

'📚 Book > Object' 카테고리의 다른 글

13 서브클래싱과 서브타이핑  (0) 2020.04.26
12 다형성  (0) 2020.04.12
10 상속과 코드 재사용  (0) 2020.03.22
09 유연한 설계  (1) 2020.03.14
08 의존성 관리하기  (0) 2020.03.08