Java에서는 이제 언어적인 지원이 이루어지기 때문에 잘 쓰이지는 않지만 여전히 C++ 등에서는 자주 쓰이는 패턴이다. 보통 컬렉션들(C++에서는 컨테이너)에 쓰인다.
Iterator 패턴은 일련의 순서를 가진 데이터 집합에 대하여 순차적인 접근을 지원하는 패턴이다.
Iterator 패턴 클래스 다이어그램
Iterator 패턴의 구현
interface IIterator{
public boolean hasNext();
public Object next();
}
interface IContainer{
public IIterator iterator();
}
class NameContainer implements IContainer{
List<String> list = new ArrayList<String>();
public void add(String name){
list.add(name);
}
class NameIterator implements IIterator{
String current;
@Override
public boolean hasNext() {
if(list.size() == 0) return false;
if(list.indexOf(current) != list.size()-1) return true;
return false;
}
@Override
public Object next() {
if(list.size() == 0) return null;
if(list.indexOf(current) != list.size()-1){
current = list.get(list.indexOf(current) + 1);
return current;
}
return null;
}
}
@Override
public IIterator iterator() {
return new NameIterator();
}
}
사용방법
public static void main(String[] args) {
NameContainer names = new NameContainer();
names.add("Nick");
names.add("Ceasar");
names.add("Augustus");
for(IIterator iter = names.iterator(); iter.hasNext();){
String name = (String)iter.next();
System.out.println(name);
}
}
우선 데이터 집합을 가지고 있는 Container는 모두 Iterator를 제공해 줄 수 있어야 한다. 따라서 Container의 인터페이스인 IContainer와 Iterator의 인터페이스인 IIterator를 선언한다. 이는 어떤 Container를 구현하더라도 같은 방식으로 Iterator를 사용할 수 있도록 하기 위함이다. 구체 클래스들은 선언한 인터페이스들을 구현한다.
Iterator가 직접 데이터에 접근할 수 있도록 하는 것이 구현이 단순해 지므로 보통 Iterator는 Container의 내부 클래스로 구현하는 경우가 많다. 위의 예제에서도 NameContainer 내부에 NameIterator를 선언하였다. NameContainer로부터 NameIterator를 받아 오는 메소드는 iterator()인데, 이 메소드가 호출되면 NameContainer를 새로 생성하여 넘겨준다. 이렇게 해야 Iterator를 가지고 데이터에 접근하는 쓰레드가 많아도 문제 없이 동작이 가능하다.(데이터 집합의 추가/삭제로 인한 쓰레드 문제는 별도로 처리해 주어야 한다.)
'5.디자인패턴' 카테고리의 다른 글
Chain Of Responsibility 패턴 (0) | 2016.09.17 |
---|---|
Composite 패턴 (0) | 2016.09.17 |
Enum Abstract Factory 패턴 (0) | 2016.09.16 |
Proxy 패턴과 그 활용 (0) | 2016.09.16 |
Observer 패턴 (0) | 2016.09.16 |