Iterator Pattern
Iterator 디자인 패턴의 필요성과 그 구조에 대해 알아봅니다.읽는데 5분 정도 걸려요.필요성
사람마다 개발 스타일이 다르다.
하물며 List, ArrayList 등, 어떤 자료구조가 익숙하냐에 따라 사용하는 데이터 타입 역시 다르다.
만약 분업을 하는데 있어 사람 A는 List, B는 ArrayList를 사용했다고 해보자.
이렇게 자료구조가 다를 경우, 순차탐색에 있어 코드의 구현이 달라진다.
// List
for (int i=0; i<myList.length; i++) {
myList[i];
}
// ArrayList
for (int i=0; i<myArrayList.size(); i++) {
myArrayList.get(i);
}
만약 위의 순차탐색에서 동작하는 기능이 동알하다면?
자료구조가 다르다는 이유로 같은 기능을 수행하는 동작을 중복해서 작성해야 하는 이슈가 생긴다.
더 심각한건, list를 arrayList와 같이 자료구조를 바꾸기라도 하는 날에는 클라이언트가 코드를 수정해야 한다는 치명적인 문제도 있다.
Iterator Pattern
Data Collection을 순차적 접근이 필요할 때 그 방식을 Iterator와 같이 제공하는 디자인 패턴을 Iterator Pattern이라고 한다.
위의 코드를 이 디자인 패턴을 적용해 개선해보자.
public class MyListIterator implements Iterator {
Object[] data;
int position = 0;
public MyListIterator(Object[] data) {
this.data = data;
}
public Object next() {
Object obj = data[position];
position += 1;
return obj;
}
public boolean hasNext() {
if (position >= data.length || data[position] == null) {
return false;
}
return true;
}
}
public class MyList {
...
public Iterator createIterator() {
return new MyListIterator(data);
}
}
이런식으로 나만의 클래스나 Iterator를 제공하지 않는 클래스의 경우 Iterator를 생성하기 위한 클래스를 생성하여 이를 createIterator 에서 반환해주면,
순차 탐색은 createIterator에서 반환된 Iterator를 이용해서 하면 인터페이스를 통일할 수 있다.
MyArrayListIterator는 왜 안 만드는지?
기본적으로 Java에서 Collection
을 implement 하는 자료구조는 Iterator를 제공하기 때문.
따라서 얘는 Iterator 클래스를 별도로 구현하지 않아도, 바로 createIterator 메서드 내부에서 myArrayList.iterator()
와 같은 방식으로 Iterator를 생성할 수 있음.
예로 들어 Hashtable 자료구조는 values() 라는 메서드를 제공하는데, 해당 메서드는 Collection 객체(아마 ArrayList)를 반환한다.
즉, Hashtable 자료구조는 myHashtable.values().iterator() 형식으로 Iterator를 얻을 수 있음.
// List, ArrayList
while (myIterator.hasNext()) {
Object obj = myIterator.next();
}
한 단계 더 나아가 MyList, MyArrayList를 인터페이스로 묶어 createIterator를 강제할 수 있다.
공통 메서드로 createIterator를 만들어 순차 탐색시에는 Iterator를 사용하도록 유도하는 것이다.
Single Responsibility
그런데 MyListIterator 클래스를 따로 만들지 않고, 그냥 MyList에서 Iterator를 바로 implements 해서 구현하면 안되는 걸까?
그래도 상관없긴 하다.
하지만, 하나의 클래스는 하나의 역할만 수행한다는 디자인 원칙을 준수하는 것이 코드를 깔끔하게 관리할 수 있도록 도와줄 것이다.
하나의 클래스가 데이터도 관리하고, Iterator도 관리하면... 기능이 너무 복잡해지기 때문이다.