[JAVA] 컴포지션(Composition)

in·2023년 9월 8일
0

JAVA

목록 보기
9/9

✔️ 상속(Inheritance)
하위 클래스가 상위 클래스의 특성을 재정의 한 것

구현 상속(클래스 -> 클래스)의 단점
1. 캡슐화 위반
2. 유연하지 못한 설계
3. 다중 상속 불가능

상속하위 클래스가 상위 클래스의 특성을 재정의한 것 ➡️ IS-A 관계
컴포지션기존 클래스가 새로운 클래스의 구성요소가 되는 것 ➡️ HAS-A 관계

📌 컴포지션(Composition)

기존 클래스가 새로운 클래스의 구성요소가 되는 것
➡️ 상속처럼 기존의 클래스를 확장(extend)하는 것이 아닌, 새로운 클래스를 생성하여 private 필드로 기존 클래스의 인스턴스를 참조하는 방식

public class CustomHashSet<E> extends ForwardingSet {
    private int count = 0;

    public CustomHashSet(Set<E> set){
        super(set);
    }

    @Override
    public boolean add(Object o) {
        count++;
        return super.add(o);
    }

    @Override
    public boolean addAll(Collection c) {
        count += c.size();
        return super.addAll(c);
    }

    public int getCount() {
        return count;
    }

}
public class ForwardingSet<E> implements Set {

    private final Set<E> set;

    public ForwardingSet(Set<E> set){
        this.set=set;
    }

    @Override
    public int size() {
        return set.size();
    }

    @Override
    public boolean isEmpty() {
        return set.isEmpty();
    }

    @Override
    public boolean contains(Object o) {
        return set.contains(o);
    }

    @Override
    public Iterator iterator() {
        return set.iterator();
    }

    @Override
    public Object[] toArray() {
        return set.toArray();
    }

    @Override
    public boolean add(Object o) {
        return set.add((E) o);
    }

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

    @Override
    public boolean addAll(Collection c) {
        return set.addAll(c);
    }

    @Override
    public void clear() {
        set.clear();
    }

    @Override
    public boolean removeAll(Collection c) {
        return set.removeAll(c);
    }

    @Override
    public boolean retainAll(Collection c) {
        return set.retainAll(c);
    }

    @Override
    public boolean containsAll(Collection c) {
        return set.containsAll(c);
    }

    @Override
    public Object[] toArray(Object[] a) {
        return set.toArray();
    }
}

CustomHahSet은 Set 인터페이스를 implements한 ForwardingSet을 상속
➡️ HashSet의 부모클래스에 영향을 받지 않고 오버라이딩을 통해 원하는 작업 수행 가능

public class Main {
    public static void main(String[] args) {
        CustomHashSet<String> customHashSet = new CustomHashSet<>(new HashSet<>());
        List<String> test = Arrays.asList("a","b","c");
        customHashSet.addAll(test);

        System.out.println(customHashSet.getCount()); // 3
    }
}

CustomHashSet이 원하는 작업을 할 수 있도록 도와준 ForwardingSet은 위임(Delegation) 역할을 함

결론

  • 상속을 사용하는 상황은 LSP 원칙에 따라 IS-A 관계가 반드시 성립할 때만 사용해야함
  • 컴포지션 기법을 사용하는 것이 객체 지향적인 설계를 할 때 유연함을 갖출 수 있음

[참고 자료]

🔗링크
🔗링크

0개의 댓글