우리가 프로그램을 작성할 때에 List 등의 자료구조에 순차 탐색해야하는 경우가 있다. 이럴 때에 iterator 패턴을 이용하여 자료를 탐색하는 부분을 캡슐화하여 사용할 수 있도록 한다. 반복자 패턴을 이용할 경우, 자료와 자료를 이용하고자 하는 객체의 결합을 줄일 수 있다.
반복자 패턴은 자료에 순차적으로 접근해야할 때, 그 부분을 캡슐화하여 클라이언트가 편리하게 자료를 탐색 할 수 있도록 한다.
자료 구조에 변화가 있어도 자료의 탐색하는 일은 반복자에게 맡기기에 클라이언트는 통일된 interface로 코드의 변경 없이 자료를 이용할 수 있게 된다.
위 다이어 그램은 Iterator 패턴의 UML 다이어그램이다.
iterator과 aggregate 클래스가 있고 그 둘을 이용하는 client가 있다.
Aggregate가 우리가 이용하는 자료구조이다. 확장성을 위하여 interface로 제작하였고, 이를 상속 받은 concreteAggregate가 있다.
이 Aggregate 클래스의 자료를 순차 탐색하기 위한 Iterator 클래스가 있다. 다른 자료 구조로 확장될 경우를 고려하여 interface로 되어 있다. concreteIterator는 특정 자료구조에 맞게 제작된 iterator클래스이다. 내부의 next, first isDone, currentItem등을 이용하여 자료를 탐색할 수 있다. 자료에 접근하기 위하여 참조 표시가 되어있다.
다음과 같은 클라이언트 프로그램이 작동하도록 하려고 한다. 클라이언트는 Topic 클래스를 이용하여 리스트에 topic을 생성하고 순차 탐색하려고 한다.
이용하고자 하는 Topic 클래스는 다음과 같다.
public class Topic {
private String name;
public Topic(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Topic[] topics = new Topic[5];
topics[0] = new Topic("topic1");
topics[1] = new Topic("topic2");
topics[2] = new Topic("topic3");
topics[3] = new Topic("topic4");
topics[4] = new Topic("topic5");
List<Topic> list = new TopicList(topics);
Iterator<Topic> iterator = list.iterator();
while(iterator.hasNext()) {
Topic currentTopic = iterator.next();
System.out.println(currentTopic.getName());
}
}
}
사용된 List 는 다음과 같다. 이는 위 uml 다이어그램에서 본 Aggregate 인터페이스이다.
public interface List<E> {
Iterator<E> iterator();
}
Aggreagte 인터페이스를 상속하여 concreteAggregate인 TopicList를 만들었다. TopicList는 리스트를 탐색할 수 있도록 TopicIterator를 생성한다. Topic은 클라이언트가 직접 이용할 수 없고 iterater을 통하여 이용하도록 private로 선언하였다.
public class TopicList implements List<Topic>{
private Topic[] topics;
public TopicList(Topic[] topics)
{
this.topics = topics;
}
@Override
public Iterator<Topic> iterator() {
return new TopicIterator(topics);
}
}
아래는 Iterator 인터페이스이다. 자료구조에 따라서 reset, next, currentItem, hasNext를 지원하도록 구현하지 않은 상태로 선언되어있다. 이는 클라이언트가 이용할 인터페이스이다.
public interface Iterator<E> {
void reset();
E next();
E currentItem();
boolean hasNext();
}
Iterator을 상속 받은 TopicIterator이다. TopicList를 탐색하도록 만들어진 클래스이다. topicList에 맞는 형태로 함수들이 구현이 되어있다.
public class TopicIterator implements Iterator<Topic>{
private Topic[] topics;
private int position;
public TopicIterator(Topic[] topics)
{
this.topics = topics;
position = 0;
}
@Override
public void reset() {
position = 0;
}
@Override
public Topic next() {
return topics[position++];
}
@Override
public Topic currentItem() {
return topics[position];
}
@Override
public boolean hasNext() {
if(position >= topics.length)
return false;
return true;
}
}
위 설계를 uml 다이어그램으로 표현하면 아래와 같다.