for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
for문의 i++에서 i를 하나씩 증가시킬때마다 다음의 요소로 진행된다.
이때, i의 기능을 추상화하여 일반화한 것을 디자인 패턴에서는 Iterator 패턴이라고 한다.
Iterator 패턴은 무엇인가 많이 모여 있을 때 이를 순서대로 가리키며 전체를 검색하고 처리를 반복하는 것.
iterate라는 영단어는 무언가를 '반복하다'라는 뜻.
그래서 '반복자'라고도 한다.
Iterable 인터페이스
처리를 반복할 대상을 나타내는 것.
이 인터페이스를 구현하는 클래스는 배열처럼 '뭔자 많이 모여 있는 것' 즉, '집합체'가 된다.
Iterable은 '반복 가능'이라는 뜻.
Iterator 인터페이스
하나하나의 요소 처리를 반복하기 위한 것. 루프 변수와 같은 역할을 함.
BookShelf 클래스
implements Iterable 부분이 Iterable 인터페이스를 구현하고 있음을 나타냄.
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class BookShelf implements Iterable<Book> {
private List<Book> books;
public BookShelf(int initialsize) {
this.books = new ArrayList<>(initialsize);
}
public Book getBookAt(int index) {
return books.get(index);
}
public void appendBook(Book book) {
books.add(book);
}
public int getLength() {
return books.size();
}
@Override
public Iterator<Book> iterator() {
return new BookShelfIterator(this);
}
}
BookShelfIterator 클래스
import java.util.Iterator;
import java.util.NoSuchElementException;
public class BookShelfIterator implements Iterator<Book> {
private BookShelf bookShelf;
private int index;
public BookShelfIterator(BookShelf bookShelf) {
this.bookShelf = bookShelf;
this.index = 0;
}
@Override
public boolean hasNext() {
if (index < bookShelf.getLength()) {
return true;
} else {
return false;
}
}
@Override
public Book next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Book book = bookShelf.getBookAt(index);
index++;
return book;
}
}
Main 클래스
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
BookShelf bookShelf = new BookShelf(4);
bookShelf.appendBook(new Book("Around the World in 80 Days"));
bookShelf.appendBook(new Book("Bible"));
bookShelf.appendBook(new Book("Cinderella"));
bookShelf.appendBook(new Book("Daddy-Long-Legs"));
bookShelf.appendBook(new Book("East of Eden"));
bookShelf.appendBook(new Book("Frankenstein"));
bookShelf.appendBook(new Book("Gulliver's Travels"));
bookShelf.appendBook(new Book("Hamlet"));
// 명시적으로 Iterator를 사용하는 방법
Iterator<Book> it = bookShelf.iterator();
while (it.hasNext()) {
Book book = it.next();
System.out.println(book.getName());
}
System.out.println();
// 확장 for문을 사용하는 방법
for (Book book : bookShelf) {
System.out.println(book.getName());
}
System.out.println();
}
}
Iterator 패턴을 사용하는 이유
반복문을 사용하면 되는데 왜 굳이 Iterator를 만들어야 할까?
가장 큰 이유는 iterator를 사용함으로써 구현과 분리하여 반복할 수 있기 때문!
또한, iterator를 사용하면 모든 컬렉션에서 요소를 순차적으로 접근하는 일관된 방법을 제공한다.
bookShelf의 구현이 달라지더라도 iterator를 반환하기만 한다면 반복문(while)의 변경은 하지 않아도 된다.
Iterator<Book> it=bookShelf.iterator();
while(it.hasNext()){
Book book=it.next();
System.out.println(book.getName());
}
클래스로만 프로그래밍 하는 것이 아니라 추상 클래스나 인터페이스를 사용하여 프로그래밍 한다.
Iterable과 Iterator의 차이
Iterable
은 컬렉션을 for-each 루프와 같은 향상된 for 루프를 사용하여 순회할 수 있게 해주는 인터페이스이며, Iterator
는 컬렉션을 명시적으로 순회하고 조작하는 인터페이스입니다. Iterator
는
컬렉션의 요소를 보다 세밀하게 제어하고 수정할 때 유용합니다.
Iterable을 구현하면 Iterator도 구현했다고 볼 수 있겠네?
예, Iterable
을 구현한 클래스는 일반적으로 내부적으로 Iterator
를 구현하거나 Iterator
객체를 반환하는 iterator()
메서드를 제공합니다. 따라서 Iterable
을 구현하면
컬렉션을 순회하는 데 필요한 Iterator
도 함께 구현했다고 볼 수 있습니다.
Iterable
을 구현하면 주로 iterator()
메서드를 구현하여 해당 컬렉션의 요소를 순회할 수 있는 Iterator
객체를 반환합니다. 이 Iterator
객체는 hasNext()
와 next()
메서드를 사용하여 요소에 접근하고 순회합니다. 이렇게 함으로써 사용자는 for-each
루프와 같은 구문을 사용하여 컬렉션을 순회할 수 있습니다.
예를 들어, 다음은 Iterable
을 구현한 클래스와 그 클래스의 iterator()
메서드의 예제입니다:
import java.util.Iterator;
public class MyIterable implements Iterable<String> {
private String[] data;
public MyIterable(String[] data) {
this.data = data;
}
@Override
public Iterator<String> iterator() {
return new MyIterator(data);
}
}
class MyIterator implements Iterator<String> {
private String[] data;
private int index = 0;
public MyIterator(String[] data) {
this.data = data;
}
@Override
public boolean hasNext() {
return index < data.length;
}
@Override
public String next() {
return data[index++];
}
}
이 예제에서 MyIterable
클래스는 Iterable
을 구현하고, iterator()
메서드에서 MyIterator
객체를 생성하여 반환합니다. MyIterator
클래스는 Iterator
를
구현하고 컬렉션을 순회합니다.
따라서 MyIterable
을 사용하면 내부적으로 Iterator
도 구현되어 있어서 컬렉션을 순회할 수 있습니다.
'자바 디자인 패턴' 카테고리의 다른 글
5. Singleton - 인스턴스를 단 하나만 만든다 (0) | 2023.10.09 |
---|---|
*4. Factory Method - 하위 클래스에서 인스턴스를 만든다 (0) | 2023.10.08 |
3. Template Method - 하위 클레스에서 구체적으로 처리한다 (0) | 2023.10.06 |
2. Adapter - 사이에 끼워 재사용한다 (0) | 2023.10.05 |
0. 디자인 패턴을 배우기 전에 (0) | 2023.09.26 |