cs/ODOQ

[ODOQ] 일급 컬렉션

icodesiuuuu 2024. 11. 27. 23:35

[One Day One Question]

일급 컬렉션에 대해서 설명해 주세요


일급 컬렉션(First-class Collection)은 객체 지향 설계에서 컬렉션(리스트, 맵, 세트 등)을 다룰 때 사용하는 설계 패턴입니다. 단순히 컬렉션을 감싸는 클래스를 만드는 것처럼 보이지만, 이 패턴을 활용하면 설계의 명확성과 유지보수성을 크게 향상시킬 수 있습니다.

 

일급 컬렉션의 특징

  1. 단일 컬렉션만 포함
    • 컬렉션 외에 다른 멤버 변수를 가지지 않습니다.
    • 해당 클래스를 통해 컬렉션에 대한 작업을 수행합니다.
      public class Members {
          private final List<Member> members; // 단일 컬렉션
      
          public Members(List<Member> members) {
              this.members = new ArrayList<>(members); 
          }
      }
  2. 불변성(Immutable)
    • 컬렉션 내부 데이터를 직접 수정하지 못하도록 보장합니다.
    • 데이터를 변경할 때는 새로운 일급 컬렉션을 반환합니다.
      public Members add(Member member) {
          List<Member> newMembers = new ArrayList<>(members);
          newMembers.add(member);
          return new Members(newMembers); // 새로운 인스턴스 반환
      }

      Members teamMembers = new Members(List.of(new Member("Alice")));
      Members updatedMembers = teamMembers.add(new Member("Bob"));
      
      System.out.println(teamMembers.toList().size()); // 출력: 1 (원본 변경 없음)
      System.out.println(updatedMembers.toList().size()); // 출력: 2 (새로운 컬렉션 생성)
       
    • final 변수와 불변성의 차이점
      더보기
      final은 불변이 아니라 재할당만 불가!
      final List<String> name = new ArrayList<>();
      name.add("park");
      name.add("kim");
      name.add("lee"); //데이터 변경, 추가 가능
      
      name = new ArrayList<>(); //error!! 재할당만 불가

       
      특징 final 변수불변성(Immutable)
      기능 변수에 할당된 참조를 변경할 수 없게 함 객체의 내부 상태를 변경할 수 없게 함
      초점 변수의 참조 자체에 초점 객체의 상태 관리에 초점
      내부 데이터 변경 내부 데이터를 변경할 수 있음 (final은 참조만 고정) 내부 데이터를 변경할 수 없음 (완전히 불변)
      적용 대상 변수나 필드에 적용 객체(클래스)의 설계와 구현 방식
  3. 비즈니스 로직 캡슐화
    • 컬렉션에 대한 처리(검색, 추가, 삭제, 필터링 등)를 캡슐화하여 외부에서 직접 컬렉션에 접근하지 못하게 합니다.
      public Members filter(Predicate<Member> condition) {
          List<Member> filtered = members.stream()
                                         .filter(condition)
                                         .collect(Collectors.toList());
          return new Members(filtered);
      }

      Members filtered = updatedMembers.filter(member -> member.getName().startsWith("A"));
      System.out.println(filtered.toList().size()); // "A"로 시작하는 멤버만 반환


  4. 컬렉션 사용의 일관성 유지
    • 일급 컬렉션을 통해 컬렉션 조작 방법을 통일할 수 있습니다.
      public int size() {
          return members.size(); // 크기 확인
      }
      
      public boolean contains(Member member) {
          return members.contains(member); // 특정 멤버 포함 여부
      }
      System.out.println(updatedMembers.size()); // 크기: 2
      System.out.println(updatedMembers.contains(new Member("Alice"))); // 포함 여부: true


 

 

장점

1. 비즈니스 규칙 강제

컬렉션에 비즈니스 규칙을 추가하여 잘못된 데이터 입력을 방지할 수 있습니다.

public Members add(Member member) {
    if (members.contains(member)) {
        throw new IllegalArgumentException("중복된 멤버는 추가할 수 없습니다.");
    }
    List<Member> newMembers = new ArrayList<>(members);
    newMembers.add(member);
    return new Members(newMembers);
}
Members teamMembers = new Members(List.of(new Member("Alice")));
teamMembers = teamMembers.add(new Member("Bob")); // 정상 동작
teamMembers = teamMembers.add(new Member("Alice")); // 예외 발생

 

2. 코드 가독성과 유지보수성 향상

컬렉션 조작을 캡슐화하여 중복 코드를 제거하고 가독성을 높입니다.

public Members filterActiveMembers() {
    return filter(Member::isActive); // 활성 상태인 멤버만 필터링
}
Members activeMembers = teamMembers.filterActiveMembers();
System.out.println(activeMembers.toList());

 

3. 객체 지향 설계 강화

컬렉션을 단순 데이터가 아니라 객체로 다루어 책임을 분리합니다.

public Members sortByName() {
    List<Member> sorted = new ArrayList<>(members);
    sorted.sort(Comparator.comparing(Member::getName));
    return new Members(sorted);
}
Members sortedMembers = teamMembers.sortByName();
System.out.println(sortedMembers.toList());

 

4. 컬렉션 상태 관리

외부에서 컬렉션을 직접 변경하지 못하도록 상태를 안전하게 관리합니다.

public List<Member> toList() {
    return Collections.unmodifiableList(members); // 수정 불가 리스트 반환
}
List<Member> membersList = teamMembers.toList();
membersList.add(new Member("Charlie")); // UnsupportedOperationException 발생

'cs > ODOQ' 카테고리의 다른 글

[ODOQ] 트랜잭션 격리수준  (0) 2024.11.29
[ODOQ] DB 인덱스(Index)  (0) 2024.11.28
[ODOQ] Checked Exception, Unchecked Exception  (0) 2024.11.26
[ODOQ] JPA의 N + 1  (0) 2024.11.25
[ODOQ] TCP와 UDP의 차이점  (1) 2024.11.25