[Effective Java] 상속 대신 컴포지션 이용하기
Effective Java에 따르면 상속 대신 컴포지션을 이용하라는 말이 있다.
이는 상속을 사용하게 되는 경우 상위클래스가 하위클래스에 영향을 끼쳐 대응할 수 없는 오류를 야기할 수 도 있고, 추후에 수정이 일어날때 영향도가 높아 손봐야할 코드가 많아질 수 있다. (만약 상속을 정말 써야한다면 완벽에 가까운 설계를 하고 심사숙고하여 사용하길 바란다. 즉, 완벽한 is-a 관계가 유지될 때 상속을 사용하자)
이를 대응하기 위한 방법으로 우리는 컴포지션 패턴을 이용할 수 있다. 아래 예시를 보자
간단하게 여행사의 여행 정보를 예약하는 시스템을 만든다고 가정했다. (설명을 위한 예제이니 양해부탁드린다.)
interface TravelInfo {
void reserve();
}
class Accommodation implements TravelInfo {
private String description;
public void reserve() {
// 숙소 예약 로직 구현 ...
}
}
class Activity implements TravelInfo {
private String description;
public void reserve() {
// 액티비티 예약 로직 구현 ...
}
}
class Restaurant implements TravelInfo {
private String description;
public void reserve() {
// 식당 예약 로직 구현 ...
}
}
위의 로직을 보면 알겠지만 TravelInfo 인터페이스를 구현하여 각종 여행 상품을 예약하는 로직을 다르게 구현할 수가 있다.
그런데 갑자기 패키지 여행 상품을 한번에 관리하는 기능을 만들어달라는 요구를 받았다고 가정하자. 이때 우리는 컴포지션 패턴을 이용해 문제를 해결할 수 있다. (다시한번 말하지만 완전 허접한 예시이다 ..)
class PackageTravel implements TravelInfo {
private List<TravelInfo> travels;
public void reserve() {
// 패키지 여행정보들을 예약한다
}
}
위에서 보시면 여행정보를 클래스가 포함(컴포지션)하여 가지고 있다. 이러한 클래스를 Wrapper Class라고 부른다. 이렇게 컴포지션 패턴을 사용하는 방식이 클래스를 확장하는 방식보다 훨씬 견고하고 안전하니 잘 기억해두자.
위의 예시는 아주 간단하게 컴포지션 패턴을 사용한것인데, 아래링크에서 조금더 구체적으로 작성해둔 컴포지트 패턴이 있으니 참고 부탁드린다.
https://devkingdom.tistory.com/356