Iterator란? |
Iterator : 반복자
C++에서 자주 사용하던 iterator와 같은 것
이터레이터는 컨테이너의 원소들을 순회할수 있는 객체이다.
포인터와 유사하게 사용되며 컨테이너에서의 특정 위치를 가리킨다.
이터레이터 패턴이란 |
Iterator를 구현하는 패턴이다.
즉 이터레이터 패턴이란 객체의 컬렉션의 요소에 대한 구체적인 구현은 노출시키지 않고, 컬렉션을 순회하고 컬렉션의 요소에 접근할 수 있는 방법을 Iterator 객체로 만들어서 반복을 캡슐화 하는 패턴이다.
예를들어 어떤 데이터는 Array로 구현되어 있고 또 다른 어떤 데이터는 List로 구현되어 있고 또 어떤 데이터는 Deque로, Vector로 등등 다양하게 구현되어 있을 때
Client 입장에서는 그냥 어떻게 구현되어 있건 모두 동일한 방법으로 데이터에 접근하게 만들어주는 패턴
이터레이터 패턴의 구조 |
1) Iterator(반복자)
- 컬렉션의 요소를 순회/접근하는 인터페이스 제공
- hasNext() : 다음 요소가 있는지 확인하는 함수
- next() : 다음 요소로 이동하는 함수
2) ConcreteIterator
- 실제 컬렉션에 대한 순회/접근 동작 구현
3) Aggregate(집합체)
- 자료구조를 모아둔 컬렉션
- 집합을 나타내는 인터페이스와 함께 이터레이터를 생성하는 메서드 인터페이스도 제공
4) ConcreteAggregate
- Aggregate 인터페이스를 구현 및 이터레이터 생성메서드를 구현
이터레이터 패턴 구현 예시 |
포인터와 유사하게 작동하기 위해선 접근연산자, 대입연산자, 비교연산자, 증감연산자 등이 정의되어 있어야 한다.
아래 코드에선 List가 ConcreteAggregate에 해당
// 데이터를 저장할 기본 노드
template<typename T>
class Node
{
public:
T data;
Node<T>* next;
Node(const T& d, Node<T>* ptr) {
data = d;
next = ptr;
}
};
// Iterator 클래스
template<typename T>
class Iterator
{
private:
Node<T>* current;
public:
Iterator(Node<T>* p = nullptr) : current(p) {}
Iterator& operator++() {
current = current->next;
return *this;
}
T& operator*() { return current->data; }
bool operator==(const Iterator& ref) { return current == ref.current; }
bool operator!=(const Iterator& ref) { return current != ref.current; }
};
// 위에서 구현한 Iterator를 사용하는 list 컨테이너
template<typename T>
class List
{
private:
Node<T>* head;
public:
List() : head(nullptr) {}
void push_front(const T& n) {
head = new Node<T>(n, head);
}
// 컨테이너가 멤버로 Iterator를 가짐으로써 List<int>::iterator처럼 사용 가능
typedef Iterator<T> iterator;
iterator begin() { return iterator(head); }
iterator end() { return iterator(nullptr); }
};
#include <iostream>
// 사용 예시
void main()
{
List<int> list;
list.push_front(10);
list.push_front(20);
list.push_front(30);
for (List<int>::iterator iter = list.begin(); iter != list.end(); ++iter) {
std::cout << *iter << ' ';
}
}
※ 참고 문헌