반복자 패턴
Last updated
Last updated
객체를 모아둔 컬렉션 반복 작업 처리를 컬렉션 구현에 의존하지 않고 모두 동일하게 수행하고 싶은 경우, 반복하는 행위를 캡슐화하는 인터페이스를 두도록 한다.
예를 들어 리스트, 셋, 트리 등의 컬렉션을 어떻게 순회할 지는 반복자 구현체가 결정한다. 사용자는 반복자 구현체가 제공하는 메서드를 사용해 하나씩 꺼내오기만 하면 될 것이다.
컬렉션의 구현 방법을 노출하지 않으면서 집합체 내의 모든 항목에 접근하는 방법을 제공하는 패턴이다.
모든 항목에 접근하는 작업을 컬렉션 객체가 아닌 반복자 객체가 맡게 된다.
장점
반복자가 구현되어 있다면 어떤 컬렉션이든 동일한 순환문을 통해 처리할 수 있다.
반복문이 필요한 부분에서는 반복자 인터페이스만 알면 된다.
반복하는 부분에 변경이 필요하면 반복자만 변경하면 되므로 SRP(단일 역할 원칙)을 지킨다.
클라이언트는 반복자 인터페이스에만 의존하므로 IRP(인터페이스 의존 법칙)을 지킨다.
새로운 타입의 컬렉션들에 대해 반복자들을 구현할 수 있으며, 기존의 코드에 영향을 주지 않은 채 사용할 수 있기 때문에 OCP(개방 폐쇄 원칙)을 지킨다.
단점
단순한 컬렉션들을 사용하는 경우 반복자 패턴이 과할 수 있다.
일부 컬렉션들에서는 직접 탐색하는 것보다 비효율적일 수 있다. ArrayList의 경우 특정 위치에 쉽게 접근할 수 있지만 LinkedList의 경우 특정 노드를 저장해두어야만 하는 것이 그 예이다.
Iterator 인터페이스를 정의하여 어떠한 컬렉션 구현체이든 반복할 수 있도록 한다.
Iterator 구현체에는 컬렉션과 현재까지의 반복 작업 처리 위치를 저장하고, next() 메서드로는 다음 원소를 제공하고, hasNext() 메서드로는 다음 원소가 있는지 여부를 제공한다.
Collection 인터페이스는 Iterable 인터페이스를 상속받는다. 따라서 Collection 구현체들은 반복자(Iterator 구현체)를 반환하는 iterator()
메서드와 반복 작업을 내부적으로 수행하도록 하는 forEach(Consumer<? super T> action)
메서드를 제공한다.
각종 프로퍼티를 저장하는 클래스에서 Iterable을 구현하여 iterator 메서드를 오버라이드했다.
내부에 있는 프로퍼티 데이터들은 변경되면 안되므로 Iterator의 remove 메서드는 UnsupportedOperationException 예외를 던지며 지원하지 않도록 했다.
Spring에서는 여러 Iterator 들을 등록하여 모든 Iterator의 아이템을 순회하도록 할 수 있는 클래스를 제공한다.
내부적으로 CompositeSet, CompositeMap 등을 구현할 때 사용된다.