이터레이터 패턴
집합 객체 내부 구조를 노출시키지 않고 순회하는 방법을 제공하는 패턴
- 집합 객체를 순회하는 클라이언트 코드를 변경하지 않고 다양한 순회 방법을 제공할 수 있다.
이터레이터 패턴 적용 전
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
참고
'디자인 패턴' 카테고리의 다른 글
메멘토 패턴 (Memento Pattern) (0) | 2022.08.12 |
---|---|
중재자 패턴 (Mediator pattern) (0) | 2022.08.11 |
인터프리터 패턴 (Interpreter Pattern) (0) | 2022.08.03 |
커맨드 패턴 (Command Pattern) (0) | 2022.08.02 |
책임 연쇄 패턴 (Chain of Responsibility Pattern) (0) | 2022.08.02 |