티스토리 뷰

반복자 패턴이란?

반복자 패턴은 자세한 표현방법을 나타내지 않고, 객체 집합의 요소들을 순차적으로 접근하게 하는데 사용한다. 별도의 이터레이터 객체를 반환 받아 이를 이용해 순회하기 때문에, 집합체의 내부 구조를 노출하지 않고 순회 할 수 있다는 장점이 있고, 리스트 객체와 방문하는 프로세스 사이의 결합을 줄인다. 

자바의 컬렉션 프레임워크(JCF)에서 각종 컬렉션을 무리없이 순회할수 있는 것도 내부에 미리 이터레이터 패턴이 적용되어 있기 때문이다.

반복자 패턴 사용 법

  • Aggregate (인터페이스) : Iterator의 집합체 컬렉션으로, ConcreateIterator 객체를 반환하는 인터페이스를 제공한다.
  • ConcreateAggregate (클래스) : Aggregate를 구현하는 집합체 구현체
  • Iterator (인터페이스) : 집합체 내의 요소들을 순서대로 검색하기 위한 인터페이스를 제공한다.
    • hasNext() : 순회할 다음 요소가 있는지 확인 (true / false)
    • next() : 요소를 반환하고 다음 요소를 반환할 준비를 하기 위해 커서를 이동시킴
  • ConcreateIterator (클래스) : Iterator를 구현하는 반복자 객체
    • ConcreateAggregate가 구현한 메서드로부터 생성되며, ConcreateAggregate 의 컬렉션을 참조하여 순회한다.
    • 어떤 전략으로 순회할지에 대한 로직을 구체화 한다.
public interface Aggregate {
    Iterator createIterator();
}
public class ConcreteAggregate implements Aggregate {
    private Object[] items;
    private int size;

    public ConcreteAggregate(int size) {
        this.items = new Object[size];
        this.size = size;
    }

    public void setItem(int index, Object item) {
        items[index] = item;
    }

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

    public Object getItem(int index) {
        return items[index];
    }

    public int getSize() {
        return size;
    }
}
public interface Iterator<T> {
    boolean hasNext();
    T next();
}

public class ConcreteIterator implements Iterator<Object> {
    private ConcreteAggregate aggregate;
    private int currentIndex;

    public ConcreteIterator(ConcreteAggregate aggregate) {
        this.aggregate = aggregate;
        this.currentIndex = 0;
    }

    @Override
    public boolean hasNext() {
        return currentIndex < aggregate.getSize();
    }

    @Override
    public Object next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        return aggregate.getItem(currentIndex++);
    }
}
public class Client {
    public static void main(String[] args) {
        ConcreteAggregate aggregate = new ConcreteAggregate(10);
        for (int i = 0; i < 10; i++) {
            aggregate.setItem(i, "Item " + i);
        }

        Iterator iterator = aggregate.createIterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

패턴 사용 시기

  • 컬렉션에 상과없이 객체 접근 순회 방식을 통일하고자 할 때
  • 컬렉션을 순회하는 다양한 방법을 지원하고 싶을 때
  • 컬렉션의 복잡한 내부 구조를 클라이언트로부터 숨기고 싶은 경우
  • 데이터 저장 컬렉션 종류가 변경 가능성이 있을 때

패턴 장점

  • 일관된 이터레이터 인터페이스를 사용해 여러 형태의 컬렉션에 대해 동일한 순회 방법을 제공한다.
  • 컬렉션의 내부 구조 및 순회 방식을 알지 안항도 된다.
  • 집합체의 구현과 접근하는 처리 부분을 반복자 객체로 분리해 결합도를 줄일 수 있다.
  • 순회 알고리즘을 별도의 반복자 객체에 추출해 각 클래스의 책임을 분리해 SRP를 준수
  • 데이터 저장 컬렉션 종류가 변경되어도 클라이언트 구현 코드는 손상되지 않아 수정에는 닫혀 있어 OCP를 준수

패턴 단점

  • 클래스가 늘어나고 복잡도가 증가한다.
  • 구현 방법에 따라 캡슐화를 위배할 수 있다.

'CS > Design Pattern' 카테고리의 다른 글

리팩토링  (2) 2024.06.10
데코레이터 패턴 (Decorater Pattern)  (0) 2024.06.10
커맨드 패턴 (Command Pattern)  (0) 2024.06.10
전략 패턴, 스트래티지 패턴 (Strategy Pattern)  (0) 2024.06.10
상태 패턴 (State pattern)  (0) 2024.06.10