반복자 패턴(Iterator Pattern)

구교석·2024년 4월 8일
post-thumbnail

반복자 패턴이란?

String[] stringArray = {"월", "화", "수", "목", "금", "토", "일"};

for (int i = 0; i < stringArray.length; i++) {
    System.out.println(stringArray[i]);
}

위와같은 코드가 있을 때 컨테이너는 stringArray 배열을 지칭하고 반복자는 변수 i를 지칭합니다. 여기서 중요한것은 변수 i 인데요, i는 다음과 같은 기능을 합니다.

• 현재 가로지르고 있는 배열의 위치를 나타낸다.
• 값을 증가시켜 컨테이너의 모든 요소들에 접근할수 있도록 해준다.

위 코드에서 i가 하고 있는 기능을 추상화 하여 일반화 한 것을 반복자 패턴이라고 합니다. 더 쉽게 풀어쓰자면 각기 다른 자료구조(컬렉션)가 있다고 가정했을 때 이 각각의 자료구조에 접근할 수 있는 방법을 모두 알 필요 없이 반복기능만 통일하여 일반화 한 패턴 정도로 이해하시면 될 것 같습니다.

반복자 패턴에서 중요하게 여겨지는 원칙은 SRP(단일 책임 원칙) 입니다. 단일 책임 원칙이란 클래스는 하나의 책임만 가져야 하며, 클래스를 변경하는 이유도 한개여야 함을 의미합니다.

반복자 패턴 구조

● Iterator : 집합체의 요소들을 순서대로 검색하기 위한 인터페이스 정의

● ConcreateIterator : Iterator 인터페이스를 구현함

● Aggregate : 여러 요소들로 이루어져 있는 집합체

● ConcreateAggregate : Aggreagate 인터페이스를 구현하는 클래스

반복자 패턴 코드

public class Book {
    private String name;

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

    public String getName() {
        return name;
    }
}
public interface Aggregate {

    Iterator createIterator();
}
public class BookShelf implements Aggregate {
    private Book[] books; // 책의 집합
    private int last = 0; // 마지막 책이 꽂힌 위치

    public BookShelf(int size) {
        books = new Book[size];
    }

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

    public int getLength() {
        return last;
    }

    // 책꽂이에 책을 꽂는다
    public void appendBook(Book book) {
        if (last < books.length) {
            this.books[last] = book;
            last++;
        } else {
            System.out.println("책꽂이가 꽉 찼습니다!");
        }
    }

    @Override
    public Iterator createIterator() {
        return new BookShelfIterator(this);
    }
}
public class BookShelfIterator implements Iterator<Book> {
    private BookShelf bookShelf; // 검색을 수행할 책꽂이
    private int index = 0; // 현재 처리할 책의 위치

    public BookShelfIterator(BookShelf bookShelf) {
        this.bookShelf = bookShelf;
    }

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

    @Override
    public Book next() {
        Book book = bookShelf.getBook(index);
        index++;
        return book;
    }
}
  public static void main(String[] args) {
        BookShelf bookShelf = new BookShelf(10);

        Book book1 = new Book("문학동네");
        Book book2 = new Book("너무 한낮의 연애");
        Book book3 = new Book("늑대의 문장");

        bookShelf.appendBook(book1);
        bookShelf.appendBook(book2);
        bookShelf.appendBook(book3);

        System.out.println("현재 꽂혀있는 책 : " + bookShelf.getLength() + "권");

        Iterator it = bookShelf.createIterator();
        while (it.hasNext()) {
            Book book = (Book) it.next();
            System.out.println(book.getName());
        }
    }

결과

>>>현재 꽂혀있는 책 : 3>>>문학동네
>>>너무 한낮의 연애
>>>늑대의 문장

장단점

장점

  1. 집합체 클래스의 응집도를 높여준다.
  2. 집합체 내에서 어떤 식으로 일이 처리되는지 알 필요 없이, 집합체 안에 들어있는 모든 항목에 접근 할 수 있게 해준다.
  3. 모든 항목에 일일이 접근하는 작업을 컬렉션 객체가 아닌 이터레이터 객체에서 맡게 된다. 이렇게 하면, 집합체의 인터페이스 및 구현이 간단해질 뿐만 아니라, 집합체에서는 반복 작업에서 손을 떼고 원래 자신이 할 일에만 전념할 수 있다.

단점

  1. 단순한 순회를 구현하는 경우 클래스만 많아져 복잡도가 증가할 수 있다.

결론

반복자 패턴을 사용하면 구현 클래스 내부에서 어떤 식으로 일이 처리되는지 알 필요 없이(자료구조와 관계없이) 컬렉션 내부의 모든 항목에 접근할 수 있습니다. 다만 Iterator를 사용하는 경우 for loop를 사용하는 것 보다 성능이 떨어질 수 있으니 주의가 필요합니다.

참고 사이트


08 반복자 패턴 (Iterator Pattern)
[Design Pattern] 이터레이터 패턴 (iterator pattern)
반복자 패턴 (Iterator Pattern)

profile
끊임없이 노력하는 개발자

0개의 댓글