반복자 패턴

이정석·2023년 6월 24일
0

디자인패턴

목록 보기
23/23
post-thumbnail

반복자 패턴이란?

컬렉션을 사용하는 요소들에 대해서 순차적으로 접근하는 인터페이스를 제공하는 패턴으로 내부 자료구조를 노출하지 않은 상태로 접근기회를 제공해주는 패턴이다.


문제상황

1. 여러개의 Book을 저장하는 Bookshelf 클래스가 있다.

class Bookshelf {
    private ArrayList<String> books;

    Bookshelf() {
        books = new ArrayList<>();
        books.add("Book 1");
        books.add("Book 2");
        books.add("Book 3");
    }

    public ArrayList<String> getBooks() {
        return books;
    }
}

2. Bookself의 book에 접근하기 위해 Client는 다음과 같은 코드로 작성할 수 있다.

public class Client {
    public static void main(String[] args) {
        Bookshelf bookshelf = new Bookshelf();

        ArrayList<String> books = bookshelf.getBooks();
        for (int i = 0; i < books.size(); i++) {
            System.out.println(books.get(i));
        }
    }
}

위 상황에서 만약 Bookself의 자료구조가 ArrayList가 아닌 다른 자료구조로 바뀐다면, Client의 books.get() 메소드를 무조건 제공한다고 할 수 없다. 즉, Client의 코드를 바꾸어야 한다.

books를 순회하는 인터페이스를 제공하도록 Iterator 인터페이스를 통해 접근하도록 하자


구조

  1. Iterator.: Collection를 순회하는데 필요한 메서드를 정의한 인터페이스이다.
  2. ConcreteIterator.: Iterator를 상속받아 구현한 클래스로 ConcreteCollection를 순회하는 과정을 구현한다.
  3. IterableCollection.: 객체들의 집합을 반환하는 createIterator 메소드를 정의한 인터페이스이다.
  4. ConcreteCollection.: IterableCollection를 상속받은 클래스로 Collection에 속한 객체들을 저장하고 ConcreteIterator를 생성하는 createIterator를 구현한다.

코드(JAVA)

1. Iterator

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

2. Bookshelf

class Bookshelf {
    private ArrayList<String> books;

    Bookshelf() {
        books = new ArrayList<>();
        books.add("Book 1");
        books.add("Book 2");
        books.add("Book 3");
    }

    public Iterator getIterator() {
        return new BookIterator(this.books);
    }
}

ConcreteCollection에 해당하는 Bookshelf로 이전의 getBooks대신 getIterator로 순회하기 위한 Iterator를 생성해 반환한다.

3. BookIterator

class BookIterator implements Iterator {
    private ArrayList<String> books;
    private int index;

    public BookIterator(ArrayList<String> books) {
        this.books = books;
    }

    @Override
    public boolean hasNext() {
        if(index < books.size()){
            return true;
        }
        return false;
    }

    @Override
    public Object next() {
        if(this.hasNext()){
            return books.get(index++);
        }
        return null;
    }        
}

4. Client

public class Client {
    public static void main(String[] args) {
        Bookshelf bookshelf = new Bookshelf();
        Iterator iter = bookshelf.getIterator();

        while (iter.hasNext()) {
            String book = (String)iter.next();
            System.out.println(book);
        }
    }
}

반복자 패턴이 적용되면 Bookself의 내부 자료구조가 ArrayList에서 다른 자료구조로 바뀌어도 실제 순회로직을 담당하는 BookIterator만 바꾸어주면 된다. 즉, Client에는 영향을 미치지 않는다.

profile
게임 개발자가 되고 싶은 한 소?년

0개의 댓글