문제 및 이론 정리/디자인패턴

[디자인패턴] Iterator - 처리를 반복한다

hail2y 2025. 2. 18. 00:47

책 [JAVA 언어로 배우는 디자인 패턴 입문 3판;유키 히로시 저]을 참고하여 작성하였습니다. 

 

Iterable<E> 집합체 인터페이스

Iterator<E> 처리를 반복하는 반복자 인터페이스

BookShelf implements Iterable<Book>집합체 구현 클래스

BookShelfIterator implements Iterator<Book> 반복자 구현 클래스

 

Book 각 요소 나타내는 클래스

 

 

Iterable<E> 인터페이스는 처리를 반복할 대상으로 이 인터페이스를 구현하는 클래스는 배열처럼 '뭔가 많이 모여있는 것' 이른바 '집합체'가 된다. Iterable<E> 인터페이스는 iterator 메서드가 선언되어 있다.

public interface Iterable<E> {
    public abstract Iterator<E> iterator();
}

 

Iterator<E> 인터페이스는 하나하나의 요소를 반복하기 위한 것으로 루프 변수의 역할을 한다.

  • hasNext(): 다음 요소가 있는지 확인한다
  • next(): 현재 요소를 반환한 뒤 다음 요소를 가리킨다
public interface Iterator<E> {
    public abstract boolean hasNext();
    public abstract E next();
}

 

BookShelf 클래스는 Iterable<E>를 구현했기 때문에 iterate()를 사용/호출할 수 있다. 이 역할은 집합체를 요소 하나하나 탐색해 나갈 반복자를 생성하는 것이다.

@Override 
public Iterator<Book> iterator() {
    return new BookShelfIterator(this);
}

 

실제로 집합체를 탐색해 나가는 과정은 BookShelfIterator의 hasNext(), next() 안에 구현되어 있다. 그렇기 때문에 Iterator의 구체 클래스에서는 검색에 필요한 정보, 즉 집합체의 정보를 가지고 있다. 

 

실제 사용 예시

  • 일반적으로 Java의 확장 for 문은 Iterable 인터페이스를 구현한 클래스의 인스턴스에 대해 내부적으로 Iterator를 사용하여 처리한다. 즉 Iterator 패턴을 사용한다고 볼 수 있다.
  • 이렇게 사용하면 반복 처리를 간결하게 할 수 있다. 
// 1. 명시적으로 Iterator를 사용하는 방법
Iterator<Book> it = bookShelf.iterator();
while(it.hasNext()) {
    Book book = it.next();
    System.out.println(book.getName());
}
System.out.println();

// 2. 확장된 for 문을 사용하는 방법
for(Book book: bookShelf) {
    System.out.println(book.getName());
}
System.out.println();

 

  • 집합체를 어떻게 구현하든 Iterator를 사용할 수 있다. 
    - Iterator를 사용하여 구현과 분리하여 반복할 수 있다.
    - 루프에서 집합체 구현에 의존하지 않는다.
    - 우리는 iterator()를 이용하여 반복자를 생성하고, 그의 메서드인 hasNext(), next()만 사용하면 된다.
  • 추상 클래스와 인터페이스를 사용하여 프로그래밍 한다.
  • Aggregate(집합체)와 Iterator(반복자)의 대응
    - Iterator 인터페이스를 구현해 만든 구체 Iterator 클래스는 집합체에 대한 정보를 가지고 있다.
    - 집합체의 구현이 바뀐다면 그에 대한 Iterator 클래스도 바뀌어야 한다.
  • 하나의 집합체(ConcreteAggregate)에 대해 여러 개의 Iterator(ConcreteIterator)를 만들 수 있다.