본문 바로가기
Design Pattern/행동 패턴(Behavioral Patterns)

반복자(Iterator) - 행동 패턴(Behavioral Patterns)

by 김 민 준 2024. 5. 25.

 

반복자 패턴은 컬렉션(집합체)의 내부 구조를 노출하지 않고도 그 안에 들어있는 요소들을 순회(traverse)할 수 있는 방법을 제공하는 디자인 패턴이다. 이 패턴을 컬렉션을 순회하는 로직을 컬렉션 개체 외부에 정의할 수 있으므로, 컬렉션의 내부 구조가 변경되더라도 순회 로직을 변경하지 않아도 된다.

 

주요 개념 부터 살펴보자

 

1. Iterator 인터페이스 : 컬렉션 요소를 순회하는 메서드를 정의한다.

2. ConcreteIterator 클래스 : Iterator 인터페이스를 구현하며, 컬렉션 요소를 순회하는 기능을 제공한다.

3. Aggregate 인터페이스 :Iterator 개체를 반환하는 메서드를 정의한다.

4. ConcreteAggregate 클래스 : Aggregate 인터페이스를 구현하며 컬렉션을 정의하고 해당 컬렉션을 순회할 Iterator를 반환한다. 

 

 

예시 소스코드를 살펴보자. 

책 컬렉션을 순회하는 반복자 패턴이다. 

// Iterator 인터페이스: 컬렉션 요소를 순회하는 메서드를 정의
interface Iterator {
    boolean hasNext();
    Object next();
}

 

// BookIterator 클래스: Iterator 인터페이스를 구현하며, 책 컬렉션을 순회
class BookIterator implements Iterator {
    private BookCollection collection;
    private int index = 0;

    public BookIterator(BookCollection collection) {
        this.collection = collection;
    }

    @Override
    public boolean hasNext() {
        return index < collection.getLength();
    }

    @Override
    public Object next() {
        return collection.getBookAt(index++);
    }
}

 

// Aggregate 인터페이스: Iterator 객체를 반환하는 메서드를 정의
interface Aggregate {
    Iterator createIterator();
}

 

// BookCollection 클래스: Aggregate 인터페이스를 구현하며, 책 컬렉션을 정의
class BookCollection implements Aggregate {
    private Book[] books;
    private int last = 0;

    public BookCollection(int maxSize) {
        this.books = new Book[maxSize];
    }

    public void addBook(Book book) {
        this.books[last++] = book;
    }

    public Book getBookAt(int index) {
        return books[index];
    }

    public int getLength() {
        return last;
    }

    @Override
    public Iterator createIterator() {
        return new BookIterator(this);
    }
}

 

// Book 클래스: 책 정보를 나타내는 클래스
class Book {
    private String title;

    public Book(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }
}

 

// Client 클래스: BookCollection 객체를 생성하고, 이를 순회
public class IteratorPatternDemo {
    public static void main(String[] args) {
        BookCollection collection = new BookCollection(5);
        collection.addBook(new Book("Design Patterns"));
        collection.addBook(new Book("Refactoring"));
        collection.addBook(new Book("Clean Code"));

        Iterator iterator = collection.createIterator();
        while (iterator.hasNext()) {
            Book book = (Book) iterator.next();
            System.out.println("Book title: " + book.getTitle());
        }
    }
}

 

//출력
//Book title: Design Patterns
//Book title: Refactoring
//Book title: Clean Code

 

자바의 java.util.Iteator 인터페이스가 대표적인데 ArrayList, HashSet, HashMap은 모두 Iterator인터페이스를 통해 요소를 순회할 수 있다. 

 

아래 소스 코드는 HashSet의 반복자 사용 예시 소스코드이다.

 

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class HashSetIteratorExample {
    public static void main(String[] args) {
        // HashSet 생성 및 초기화
        Set<String> uniqueBooks = new HashSet<>();
        uniqueBooks.add("Design Patterns");
        uniqueBooks.add("Refactoring");
        uniqueBooks.add("Clean Code");

        // Iterator를 사용하여 요소를 순회
        Iterator<String> iterator = uniqueBooks.iterator();
        while (iterator.hasNext()) {
            String book = iterator.next();
            System.out.println("Unique book title: " + book);
        }
    }
}

 

Node.js에서는 symbol.iterator 메서드를 통해서 동일하게 사용된다.