디자인 패턴

이터레이터 패턴 (Iterator Pattern)

개발정리 2022. 8. 4. 18:23

이터레이터 패턴


집합 객체 내부 구조를 노출시키지 않고 순회하는 방법을 제공하는 패턴

  • 집합 객체를 순회하는 클라이언트 코드를 변경하지 않고 다양한 순회 방법을 제공할 수 있다.

 

 

 

이터레이터 패턴 적용 전


Board 는 Post 들을 관리하는 객체이다.

먼저 Client 코드를 살펴보자. 

 

Client

public class Client {
  public static void main(String[] args) {

    Board board = new Board();
    board.addPost("디자인 패턴 게임");
    board.addPost("디자인 패턴을 배워보아요");
    board.addPost("모든 코더들은 디자인 패턴을 학습해야할까요?");

    List<Post> posts = board.getPosts();
    for (Post post : posts) {
      System.out.println(post.getTitle());
    }
    
    posts.sort((p1,p2) -> p2.getCreatedDateTime().compareTo(p1.getCreatedDateTime()));
    for (Post post : posts) {
      System.out.println(post.getTitle());
    }
  }
}

 

 

Board

public class Board {
  List<Post> posts = new ArrayList<>();

  public void addPost(String content) {
    this.posts.add(new Post(content));
  }

  public List<Post> getPosts() {
    return posts;
  }
}

 

 

Post

@Getter
@Setter
public class Post {
  private String title;
  private LocalDateTime createdDateTime;
  
  public Post(String title) {
    this.title = title;
    this.createdDateTime = LocalDateTime.now();
  }
}

 

 

문제점

클라이언트 코드를 보면 Board 의 post 에 접근하기 위해 board 의 post 가  List 타입임을 클라이언트가 알아야한다.

이를 클라이언트가 모르도록 인터레이터 패턴을 적용해보자.

 

 

 

이터레이터 패턴 적용 후


클라이언트에게 Collection 이 아닌 Iterator 타입을 전달하기 위해서는 자바의 Iterator 인터페이스를 구현해야한다. 

작성일이 최신 순인 post iterator 를 만들어보자.

 

 

RecentPostIterator

public class RecentPostIterator implements Iterator<Post> {
  private Iterator<Post> internalIterator;

  public RecentPostIterator(Board board) {
    List<Post> posts = board.getPosts();
    posts.sort((p1,p2) -> p2.getCreatedDateTime().compareTo(p1.getCreatedDateTime()));
    this.internalIterator = posts.iterator();
  }

  @Override
  public boolean hasNext() {
    return this.internalIterator.hasNext();
  }

  @Override
  public Post next() {
    return this.internalIterator.next();
  }
}

생성자에서 sort 메소드를 사용하여 posts 를 최근에 생성된 순으로 정렬해주는 것을 볼 수 있다.

 

 

Board

public class Board {
  List<Post> posts = new ArrayList<>();

  public void addPost(String content) {
    this.posts.add(new Post(content));
  }

  public List<Post> getPosts() {
    return posts;
  }

  public Iterator<Post> getRecentPostIterator() {
    return new RecentPostIterator(this);
  }
}

 

 

Client

public class Client {
  public static void main(String[] args) {

    Board board = new Board();
    board.addPost("디자인 패턴 게임");
    board.addPost("디자인 패턴을 배워보아요");
    board.addPost("모든 코더들은 디자인 패턴을 학습해야할까요?");

    List<Post> posts = board.getPosts();
    for (Post post : posts) {
      System.out.println(post.getTitle());
    }

    System.out.println();

    // 가장 최신글 먼저 순회하기
    // posts 가 어떤 구조인지 몰라도 된다.
    Iterator<Post> recentPostIterator = board.getRecentPostIterator();
    while (recentPostIterator.hasNext()) {
      System.out.println(recentPostIterator.next().getTitle());
    }
  }
}

이제 클라이언트는 자바의 Iterator 를 사용하는 것처럼 사용하면 된다.

 

 

 

장점과 단점


장점

  • 집합 객체가 가지고 있는 객체를 손쉽게 접근할 수 있다.
    • 집합 구조가 Map, Set, List 무엇이든 전혀 몰라도된다.
  • 일관된 인터페이스를 사용해 여러 형태의 집합 구조를 순회할 수 있다. 

 

단점

  • 클래스가 늘어나고 복잡도가 증가한다.

 

 

 

실무에선 어떻게 쓰이나?


자바

  • java.util.Enumeration
  • java.util.Iterator

 

스프링

  • CompositeIterator

 

 

 

참고


 

코딩으로 학습하는 GoF의 디자인 패턴 - 인프런 | 강의

디자인 패턴을 알고 있다면 스프링 뿐 아니라 여러 다양한 기술 및 프로그래밍 언어도 보다 쉽게 학습할 수 있습니다. 또한, 보다 유연하고 재사용성이 뛰어난 객체 지향 소프트웨어를 개발할

www.inflearn.com