Iterator Pattern

1445664805_web-code

1. 개요

java에서 배열, list 등을 사용 할 때 모든 요소(element)들에 접근 하고 어떠한 값을 출력 하기 위해 다음과 같은 for 문을 주로 사용 한다.

 

이러한 반복은 배열등의 자료 구조의 0번째부터 n번째 index, 즉 array.length 까지 모든 index번째의 element에 접근하여 해당 index에 참조된 데이터를 출력 한다. 이와 같은 for문은 매우 자주 사용된다. 이러한 배열들은 element가 모여 있는 형태로서 index의 역활을 하는 ‘index 변수’가 존재 한다. 이러한 index 변수의 기능을 추상화 하여 일반적인 패턴화 한 형태가 반복자 패턴(Iterator pattern)이라고 한다.

간단하게 말해서 Iterator패턴은 어떠한 것들이 모여있는 것(집합체) 들을 순서대로 하나씩 전체를 검색하는 기능을 수행한다고 생각 하면 된다. iterator는 무엇인가를 ‘반복’한다는 의미로서 반복자 패턴이라고도 한다.

어렵게 말해보면 어떠한 반복을 캡슐화 하여 내부의 구현 방법을 노출 하지 않고 모든 요소(element)에 접근이 가능하게 한다 라는 것이다.

일상생활에서 이러한 Iterator패턴이 적용되는 예제에 대해서 생각해 보면 간단하다. 이미 수많은 예제들 중 하나인 ‘책장’에 꽂혀져 있는 ‘책’들이 그 하나의 예 이다. 책장의 컬럼에 꽂혀 있는 책들을 하나 하나 살펴보면서 ‘제목’이나 ‘저자’, ‘페이지 수’ 등의  캡슐화된 객체 ‘책’의 정보들에 접근 하는 것 이다. 그에 대한 for문을 이용한 코드는 다음과 같을 것이다.

 

이 코드를 이제 Iterator패턴을 적용하여 다음과 같이 사용 할 것이다.

 

2. 예제 및 설명

iterator_1

Aggregate : 집합체를 나타내는 인터페이스

iterator() 라는 추상 메소드는 집합체에 하나로 대응되는 Iterator를 1개 만들기 위한 것이다.

 

Iterator : 집합체의 요소(element)들을 하나씩 나열하면서 접근 할 수 있게 해주는 인터페이스

hasNext() : 집합체를 나열 중 다음 요소가 존재하는지 여부를 반환 하는 추상 메소드.

next() : 집합체 중 다음 요소를 반환하는 추상 메소드.

Iterator 패턴에서 가장중요한 2개의 추상 메소드 이다. 설명은 다음과 같다.

while 반복문을 이용하여 집합체에서 다음 요소 (next element)가 있는지를 hasNext()메소드를 통해 알아낸다. 만약 다음 요소가 있다면 next()메소드를 통해서 Object를 상속받은 어떠한 객체에 접근 할 수 있게 된다. 만약 집합체의 나열이 모두 끝나게 되면 hasNext()메소드에서는 다음 요소가 없기 때문에 false를 반환하게 될 것이다. 그러면 while반복은 끝이 나고 Iteration은 종료 된다.

이 인터페이스를 구현(Implements)하게 되는 클래스에서는 자세한 작업 내용들을 구현 하게 될 것이다. 이 예제 에서는 BookShelfIterator 클래스에서 자세하게 알아 볼 수 있다.

 

Book : 책, 으로서 집합체의 한개 요소

매우 간단한 클래스로서, 책의 정보 중 이름만 생성자를 통해서 저장한다. 그리고 getter메소드인 getName()을 통해서 책의 이름을 다시 얻을 수 있다.

 

BookShelf : Book(책)들이 모여 있는 집합체인 책장 클래스

Aggregate 인터페이스를 구현한 책장 클래스 에는 책들의 집합체 인 books배열을 가지고 있다. 이 배열에 Book객체들을 저장 할 것이다. books배열은 private로 선언 되어 있으며 index에 해당하는 Book 객체를 가져오거나 새로운 Book객체를 추가 하는 작업들 외에는 다른 접근을 허용하지 않고 있다.

iterator() 메소드는 BookShelf에 대응하기 위한 Iterator로서, BookShelfIterator라는 클래스의 인스턴스를 생성하고 그 인스턴스를 반환한다. 이 책장의 책들을 하나씩 나열하면서 접근 하고 싶다면 이 iterator()메소드를 통해서 Iterator 인스턴스를 얻고 이 인스턴스를 통해서 하나씩 나열 할 것이다.

 

BookShelfIterator : BookShelf 책장의 책들을 하나씩 나열 하고 검색 한다.

책장의 책들을 iteration하기 위해서 Iterator인터페이스를 구현(Implements) 하고 있다. bookShelf는 BookShelfIterator가 검색할 책장 이고, index는 현재 보고 있는(나열 하고 있는) 책(book)을 가리키는 reference라고 생각 하면 된다.

생성자에서 책장 객체를 받고 초기화를 한다.

hasNext()메소드 의 구현 내용은 책장에서 다음 요소가 존재 하는지 여부를 확인 하고 그 여부를 반환한다.

next()메소드 에서는현재 나열 하고 있던 책을 반환 하고 다음 요소로 접근 하기 위한 준비를 한다. 여기에서 index++ 하는 기능은 맨 위 for반복 문에서 i++ 하는것과 다를 바 없다.

 

사용 예제

MAX_SIZE의 크기를 갖는 책장을 만들고 예시로 책들을 MAX_SIZE-1만큼 넣었다. 이 책들을 하나 하나씩 나열하고 검색하기 위해서 Iterator를 만든다.

만들어진 bookShelf의 Iterator를 이용하여 다음 요소의 존재여부를 확인하여 false(다음 요소가 존재 하지 않을 경우)가 될 때까지 반복하면서 책장의 책(book)을 얻고, 책의 이름을 얻어서 출력 하게 될 것이다.

 

정리 해 봅시다.

Iterator패턴을 자세히 보면 가장 중요한 메소드 2개가 있다. 바로 hasNext()next()메소드 이다. 이 메소드는 while반복문에만 등장 하며 이 반복문은 BookShelf(집합체)의 구현에는 전혀 의존적이지 않다. 그것은 BookShelf의 내용이 변경 되어도, 예를 들어 books[]배열이 ArrayList나 Vector 컬렉션 구조체로 변경 되어도 그대로 사용 가능 하다라는 것 이다. 집합체의 구현에 의존적이지 않아 언제든지 내용을 바꿔도 그대로 사용 할 수 있어 재사용측면에서 매우 유리 하다. 다만 hasNext()와 next()메소드 가 정상적으로 잘 작동한다는 전제 하에서 가능한 일이다.

디자인 패턴은 라이브러리나 어떠한 모듈의 모임이 아니다. 단지 개발 측면에서 효율적인 개발 소스의 형태나 구조적인 면들 중 일반화 되어 그 결과가 입증되어진 것 들의 모임 이라고 할 수있다. 그런 면들 중 가장 좋은들이 바로 재 사용성 이다. 개발을 하다 보면 반복되는 패턴의 소스가 많아 지는데 이에 대한 대응에 좋은 내용인 것이다. 실제로 JAVA의 ArrayList등의 컬렉션 클래스들은 iterator()메소드 들이 존재 하며 Iterator를 사용 할 수도 있다.

예제의 Iterator패턴은 정방향으로 한번만 검색하는 단순한 형태 이다. 하지만 다른 패턴을 가질 수도 있다. 예를 들어 역방향으로 진행하거나 next말고도 previous()메소드를 가져서 정방향, 역방향으로도 진행 할 수 도 있으며, index를 따로 지정하여 그곳으로 바로 이동 할 수도 있다.

 

 

참고 : Java언어로 배우는 디자인 패턴 입문

You may also like

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.