11장 - HONGDAE-OBJECT/OOP GitHub Wiki

11장 합성과 유연한 설계

  • 코드 재사용을 위해서는 객체 합성이 클래스 상속보다 더 좋은 방법이다. [GOF94]

  • is a 관계 : 화이트박스 재사용, 상속으로 코드 재사용

  • has a 관계 : 블랙박스 재사용, 위임으로 기능의 재사용

  • 상속은 부모 클래스의 내부 구현에 대해 상세하기 알아야 하기 때문에 자식 클래스와 부모 클래스 사이의 결합도가 높아질 수 밖에 없다.

01. 상속을 합성으로 합성으로 변경하기

불필요한 인터페이스(기능) 상속 문제

  • 부적합한 부모 클래스의 오퍼레이션(기능) 상속됨
  • Stack 와 Properties 는 자료구조가 다르다!
  • 합성도 똑같은 문제 발생

메서드 오버라이딩 오작용 문제

  • 부모 클래스의 잘 만들어진 메서드는 수정할 필요가 없다!
  • addCount, add 는 재구현의 대상이 아님

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

  • 구현 자체가 이상함
  1. 상속은 부모 코드를 그대로 두고 자식 클래스로 문제를 해결
  2. super 를 쓸 경우 부모클래스의 코드를 이해하거나 수정해야 함
  3. 부모의 멤버객체, 멤버변수는 재사용 대상이 아님
  4. 위임으로 해결할 수 있지만 그렇다고 코드 반복이 줄어드는건 아님 질문) 부모클래스와 자식클래스간는 어떤 결합도? 내용 결합?

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

  • 하나의 기능을 추가하거나 수정하기 위해 불필요하게 많은 수의 클래스를 추가하거나 수정해야 한다.
  • 단일 상속만 지원하는 언어에서는 상속으로 인해 오히려 중복 코드의 양이 늘어날 수 있다. (단일 상속은 쓸때없는 생각을 차단)

기본 정책과 부가 정책 조합하기

  • 기본정책, 부가정책[사진]

  • 4개의 상태를 조합 = 10가지의 흐름이 생김
  • 상속을 사용할 문제는 아닌 것 같음.
  • 부모 클래스가 모호하고 자식 클래스만 사용해야 함.
  • 상속은 부모클래스와 자식클래스 모두 사용해야 함을 원칙

상속을 이용해서 기본 정책 구현하기

기본 정책에서 세금 정책 조합하기

기본 정책에 기본 요금 할인 정책 조합하기

중복 코드의 덫에 걸리다

  • 무리한 상속

03. 합성 관계로 변경하기

상속관계는 컴파일 타임에 결정되고 고정되기 때문에 코드를 실행하는 도중에는 변경할 수 없다.(있다!) 예제로 나온 코드도 컴파일 타임에 결정됨. (367p)

기본 정책 합성하기

부가 정책 적용하기

기본 정책과 부가 정책 합성하기

새로운 정책 추가하기

  • 클래스 하나만 추가하면 되는건 맞는 이야기
  • 클래스 하나만 추가한다 하더라도 중복코드는 제거 못함
  • 생/구/행 중 행위 패턴인 이터레이터 패턴으로 해결

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

  • 상속과 합성은 목적이 달라 비교 대상은 아님
  • 결합도는 하나의 모듈이 변경되거나 오류가 발생했을때 다른 모듈에 미치는 영향
  • 상속과 합성의 결합도도 비교 대상이 아님

04. 믹스인

  • 객체의 추상적인 인터페이스에 의존 : 기능을 사용할 테니 필요할때 알아서 맞춰라.
  • 믹스인 : 추상화 클래스
  • 상속은 정적이지만 믹스인은 동적이다
  • 핸드폰 과금 시스템의 목적은 기본 정책 과 부가 정책을 자유롭게 조합할 수 있는 설계
package com.code5.biz.comm002;

/**
 * @author skmpr
 *
 */
abstract class 핸드폰요금계산 {

	abstract 기본정책 기본정책();

	abstract 부가정책 부가정책();

	/**
	 * @return
	 */
	public long 지불할금액() {

		long 월요금 = 기본정책().요금();
		long 지불할금액 = 부가정책().요금계산(월요금);
		return 지불할금액;
	}

}


package com.code5.biz.comm002;

/**
 * @author skmpr
 *
 */
class 일반요금_할인없음 extends 핸드폰요금계산 {

	기본정책 기본정책() {
		return new 일반요금제();
	}

	부가정책 부가정책() {
		return new 할인50();
	}

	/**
	 * @param xxx
	 */
	public static void main(String[] xxx) {

		// 템플릿 패턴
		핸드폰요금계산 a = new 일반요금_할인없음();
		System.out.println(a.지불할금액());
	}

}

기본 정책 구현하기

트레이드로 부가 정책 구현하기

부가 정책 트레이드 믹스인 하기

쌓을 수 있는 변경

합성은 잘 구현된 기능을 가져다 쓰고 상속은 기존 클래스를 그대로 두고 필요 한 것만 재구현 하는 방법이다.

합성은 구현된 클래스만 사용될 가능성이 있지만 (핸드폰 요금 계산) 상속은 부모, 자식 클래스 모두 사용한다. (HashMap, HashMapSort)