티스토리 뷰

1. 이터레이터 패턴이란?

컬렉션 구현 방법을 노출시키지 않으면서도 그 집합체 안에 들어있는 모든 항목에 접근할 수 있게 해 주는 방법을 제공해준다.

구성요소

1) Iterator

-  아이템에 접근할 수 있도록 해주는 인터페이스를 정의한다.

 

2) ConcreteIterator

- Iterator 인터페이스를 구현한다.

- 집합체 내부를 접근할 때 현재 위치를 기억한다.

 

3) Aggregate

- Iterator 객체를 생성하기 위한 인터페이스를 제공한다.

 

4) ConcreteAggregate

- Iterator 생성 인터페이스를 구현하고 해당하는 ConcreteIterator 인스턴스를 반환한다.

 

2. 동기

이터레이터 패턴의 핵심은 집합체(리스트, 맵, 등등)의 각 아이템에 대한 접근과 순회하는 책임을 해당 집합체가 아닌 다른 객체인 이터레이터에게 위임하는 것이다.

 

왜 이렇게 분리하는 것이 좋은가?

디자인 원칙: 클래스를 바꾸는 이유는 한 가지 뿐이어야 한다.
응집도(cohesion): 한 클래스 또는 모듈이 특정 목적 또는 역할을 얼마나 일관되게 지원하는 지를 나타내는 척도.

이 두 가지 요소를 지킬 수 있기 때문이다.

 

이터레이터 패턴은 다음과 같은 상황에서 사용할 수 있다.

 

- 집합체의 구체적인 타입이 무엇인지 숨긴 채 내부 아이템에 대한 접근을 제공하고자 할 때

- 여러 가지 방법의 탐색 방법을 제공하고자 할 때

- 서로 다른 타입의 집합체이더라도 통일된 하나의 인터페이스를 통해 탐색할 수 있게 할 때 (polymorphic iteration)

 

3. 구현

구현 시 고려사항

1) 내부 VS 외부 이터레이터: 누가 반복을 제어하는가?

외부 이터레이터는 호출한 Caller가 반복 프로세스를 제어한다.

반복문을 제어한다는 것은 다음과 같다.

- 이터레이터 객체를 직접 생성

- 언제 반복 프로세스를 시작할지

- 언제 다음 아이템으로 넘어갈지

- 언제 반복문을 끝낼지

Iterator<String> iterator = collection.iterator(); //이터레이터를 직접 생성하고
while (iterator.hasNext()) {
    String item = iterator.next(); // 직접 다음 아이템으로 넘어가게 명시
    // Process item
}

내부 이터레이터는 컬렉션 내부에서 반복을 제어한다.

- 이터레이터 객체를 생성하거나 호출할 필요가 없으며

- 자동으로 다음 아이템으로 넘어간다.

// Java example of internal iterator
collection.forEach(item -> {
    // Process item
});

내부 이터레이터가 비교적 사용하기 더 간편하며 코드 가독성이 좋은 장점이 있으며, 외부 이터레이터는 반복 프로세스에 대한 제어를 직접 할 수 있다는 점에서 차이가 있다.

 

2) 누가 순회 알고리즘을 정의하는가?

- 이터레이터 말고 컬렉션 자체에서 현재 위치나 상태같은 것을 나타내는 커서를 저장해놓을 수 있다.

- 이 커서로 다음 아이템으로 넘어갈 수 있도록 (순회) 지원할 수 있다.

- 이를 일반적으로 next 오퍼레이션이라고 한다.

 

3) 이터레이터가 얼마나 안정적인가?

- 집합체를 순회하면서 내부 데이터를 변경하는 것은 위험할 수 있다 (추가/삭제 등 리스트 순회에 영향이 갈 수 있음).

- 안정적인 이터레이터 (robust iterator)은 집합체의 복제 없이 추가/삭제를 하더라도 순회에 지장이 없도록 하는 이터레이터를 의미한다.

- 이터레이터의 내부 상태를 변경하거나, 내부적으로 정보를 저장하여 안전한 순회를 보장한다.

 

4) 추가적인 이터레이터 기능

- 기본적인 기능 (예. next, first, isdone, currentItem) 외 skipTo 등 추가적인 이터레이터 함수를 제공할 수 있다.

 

4. 개인적인 포인트

- stream을 쓰기 때문에 딱히 신경쓰지 않아도 되는 것 같다.