Lee's Grow up

[디자인패턴/Design Pattern] Iterator Pattern ( 이터레이터 패턴 / 반복자 패턴) 본문

PROGRAMMING/디자인패턴

[디자인패턴/Design Pattern] Iterator Pattern ( 이터레이터 패턴 / 반복자 패턴)

효기로그 2019. 11. 21. 13:29
반응형

관련 내용은 [자바 언어로 배우는 디자인 패턴 입문] 이라는 책의 공부 내용을 개인적으로 정리한 내용입니다.
처음 배우는 부분이기 때문에 틀린 부분이 있으면 지적해주시면 감사하겠습니다.

1. Iterator 패턴이란 ?


Java 에서는 배열의 요소를 for문의 변수 i를 통해서 배열의 요소에 접근을 합니다.
여기서 사용되는 변수 i의 기능을 추상화해서 일반화한 것을 Iterator pattern이라고 합니다.
즉 무엇인가 많이 모여있는 것들을 순서대로 지정하면서 전체를 검색하는 처리를 실행하기 위한 것입니다.
-> 내부 구현을 노출하지 않고 집합의 원소들을 순차적으로 접근할 수 있는 방법을 제공

2. Iterator 패턴의 등장 인물


이번 포스팅에서 사용될 요소들의 역할입니다.

  • Iterator(반복자)의 역할
    1. 요소를 순서대로 검색해가는 인터페이스를 결정
    2. 다음 요소가 존재하는지 얻기 위한 hasNext()메소드와, 다음 요소를 얻기 위한 next()를 결정
  • ConcreateIterator ( 구체적인 반복자 ) 의 열할
    1. Iterator가 결정한 인터페이스를 실제로 구현합니다.
    2. 이 역할은 검색하기 위해 필요한 정보를 가지고 있어야 합니다. ex ) index라는 필드에 기록
  • Aggregate(집합체)의 역할
    1. Iterator 역할을 만들어내는 인터페이스를 결정.
    2. 내가 가지고 있는 요소를 순서대로 검색해 주는 열할을 만들어내는 메소드입니다.
  • ConcreteAggregate(구체적인 집합체)의 역할
    1. Aggregate 역할이 결정한 인터페이스를 실제로 구현하는 일을 합니다.
    2. ConcreteIterator역할의 인스턴스를 생성합니다.
Iterator 패턴의 클래스 다이어그램

3. 예제


이제 Iterator 패턴에 대해서 알아봤고, 해당 패턴을 사용한 예제로 좀 더 내용을 구체화 해보겠습니다.

예제에 사용될 클래스 다이어그램

3-1. Aggregate 인터페이스

집합체를 하나씩 나열하고, 검색하고, 조사하고 싶을 때에는 iterator 메소드를 사용해서 Iterator 인터페이스를 구현한 클래스의 인스턴스를 1개 만듭니다.

public interface Aggregate {
    public abstract Iterator iterator();
}

3-2. Iterator 인터페이스

다음 요소가 존재하는지 판단할 hasNext()메소드와 해당 인덱스의 요소를 반환 받는 next()메소드를 선언

public interface Iterator {
    public abstract boolean hasNext();
    public abstract Object next();
}

3-3. Book 클래스

필드로 name을 가지고, getter()메소드를 가지는 간단한 클래스입니다.

public class Book {
    private String name;

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

    public String getNaame() {
        return name;
    }
}

3-4. BookShelf 클래스

집합체를 다루기 위해 Aggregate 인터페이스를 구현, 재정의한 iterator메소드를 통해 iterator객체를 생성 후 반환

public class BookShelf implements Aggregate{
    private Book[] books;
    private int last = 0;

    public BookShelf ( int maxsize) {
        this.books = new Book[maxsize];
    }

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

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

    public int getLength() {
        return last;
    }

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

3-5. BookShelfIterator 클래스

BookShelf에 접근하기 위한 실제 Iterator클래스 입니다.
BookShelf의 인스턴스를 가지며, 해당 인스턴스를 통해 Book객체에 접근합니다.

public class BookShelfIterator implements Iterator {
    private BookShelf bookShelf;
    private int index;

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

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

    @Override
    public Object next() {
        Book book = bookShelf.getBookAt(index);
        index++;
        return book;
    }
}

3-5. Main 클래스

이제 Iterator Pattern을 통해 구현한 방식을 실행해 보겠습니다.

public class Main {
    public static void main(String[] args) {
        BookShelf bookShelf = new BookShelf(2);

        bookShelf.appendBook(new Book("Lee's Grow Up"));
        bookShelf.appendBook(new Book("Java Study 일지"));

        Iterator it = bookShelf.iterator();

        while(it.hasNext()) {
            Book book = (Book)it.next();
            System.out.println(book.getNaame());
        }
    }
}
실행 결과
Lee's Grow Up
java Study 일지

라는 문구를 출력합니다.

이와 같이 반복문과 동일한 출력 결과를 반환하는데 귀찮고, 어렵게 사용하는 이유는 무엇일까??
  1. 집합을 가진 객체와BookShelf와 원소를 탐색하는 영역BookShelfIterator가 분리되어 있다는 것, 이는 각각의 구현이 간단해지는 장점이 있습니다.
  2. BookShelf를 배열에서 List로 변경하더라도 탐색영역에서 hasNext(),next()메소드만 올바르게 수정한다면, 위 Main메소드의 while 루프는 전혀 변경하지 않고 그대로 사용 가능하다는 장점이 있습니다.
  3. 기존과 전혀 다른 배열을 가지는 Aggregate를 추가로 구현하더라도 Iterator만 구현해주면 동일한 구조로 사용 가능

이는 클래스를 부품처럼 사용하고, 재사용의 장점을 누릴 수 있게 해줍니다.

4. 관련 패턴


  1. Visitor 패턴: Iterator 패턴은 집합체에서 하나씩 요소를 꺼내서 세는 것이지만, Visiitor은 꺼내서 무언가 반복되는 로직을 처리해 반복 적용해가는 패턴입니다.
  2. Composite 패턴 : 재귀적인 구조를 갖는 패턴입니다.
  3. Factory Method 패턴 : iterator메소드가 Iterator 인스턴스를 작성할 때 사용하는 경우가 존재 ( link ) 
반응형
Comments