이터레이터 패턴
Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 87개 중 76번째.
Iterator 패턴은 기본 구조를 노출하지 않고 컬렉션의 요소에 순차적으로 접근하는 방법을 제공하는 행동 설계 패턴입니다. array, 연결 리스트 또는 트리로 작업하든, iterator는 요소를 순회할 수 있는 일관된 방법을 제공합니다.
이 패턴은 순회 로직을 컬렉션 자체와 분리합니다. 여기에는 두 가지 주요 구성 요소가 포함됩니다. 요소를 순회하기 위한 메서드를 정의하는 Iterator 인터페이스와, 해당 컬렉션에 대한 이터레이터를 생성하는 Iterable(또는 Aggregate)입니다.
interface Iterator<T> {
boolean hasNext();
T next();
}
interface Container<T> {
Iterator<T> createIterator();
}
class BookShelf implements Container<String> {
private String[] books;
private int count = 0;
public BookShelf(int size) {
books = new String[size];
}
public void addBook(String book) {
books[count++] = book;
}
public Iterator<String> createIterator() {
return new BookIterator();
}
private class BookIterator implements Iterator<String> {
private int index = 0;
public boolean hasNext() {
return index < count;
}
public String next() {
return books[index++];
}
}
}iterator는 its 자체 순회 상태를 유지하므로, 여러 iterator가 동일한 컬렉션을 독립적으로 순회할 수 있습니다. 클라이언트는 컬렉션이 데이터를 어떻게 저장하는지 알 필요 없이 iterator를 사용합니다.
BookShelf shelf = new BookShelf(3);
shelf.addBook("Design Patterns");
shelf.addBook("Clean Code");
Iterator<String> iterator = shelf.createIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}Java의 내장 Iterable 및 Iterator 인터페이스는 이와 정확히 같은 패턴을 따르므로, Iterable을 구현하는 모든 클래스에서 향상된 for 루프를 사용할 수 있습니다. 클라이언트 코드에 여러 순회 방법을 제공하거나 복잡한 내부 구조를 숨겨야 할 때 Iterator 패턴은 필수적입니다.
챌린지
쉬움Iterator Pattern을 사용하여 플레이리스트 시스템을 만들어 봅시다! 노래를 저장하고, 노래가 내부적으로 어떻게 저장되는지는 노출하지 않으면서 노래를 순차적으로 탐색할 수 있는 사용자 지정 iterator를 제공하는 음악 플레이리스트를 만들게 됩니다. 이는 Iterator Pattern을 사용하기에 완벽한 사례로, 깔끔하고 일관된 interface를 통해 사용자가 컬렉션을 탐색할 수 있게 합니다.
코드를 네 개의 파일로 구성합니다.
Iterator.java: 두 개의 메서드를 가진 genericIterator<T>interface를 Define합니다. 더 많은 요소가 exist하는지를 나타내는 boolean을 반환하는hasNext()와 T 타입의 다음 요소를 반환하는next()입니다.Playlist.java: 노래를 holds하는 Aggregate class를 Create합니다.Playlist는 고정된 capacity의 String array에 노래를 저장해야 하며, constructor에 전달된 capacity를 사용하고, added된 노래의 수를 추적해야 합니다. 플레이리스트에 노래를 Add하는addSong(String song)메서드를 포함하세요.Playlist에는
Iterator<String>을 반환하는createIterator()메서드가 필요합니다. 이를 위해PlaylistIterator라는 private inner class를 Create하고, 이 class가 여러분의 Iterator interface를 implements하도록 하세요. 이 inner iterator는 자체 index 위치를 유지하며 songs array를 탐색하고, 각 노래를 순서대로 반환합니다.Song.java: 노래 제목을 감싸는 간단한Songclass를 Create합니다. 제목(String)을 받는 constructor,getTitle()메서드, 그리고Playing: [title]을 반환하는toString()메서드를 가져야 합니다.Main.java: iterator 시스템을 하나로 결합합니다! 하나의 input으로 쉼표로 구분된 노래 제목 목록을 받습니다(예:Bohemian Rhapsody,Stairway to Heaven,Hotel California).capacity가 10곡인 Playlist를 Create합니다. input을 분석하고 각 노래 제목을 플레이리스트에 Add합니다. 그런 다음 플레이리스트에서 iterator를 가져와 모든 노래를 탐색하고, 각 노래를 Song 객체로 감싸서 출력합니다(이 객체는
Playing: [title]로 표시됩니다).모든 노래를 iterating한 후, 새 줄에
Playlist complete!를 출력합니다.
하나의 input으로 쉼표로 구분된 노래 제목 문자열을 받습니다.
예를 들어 input이 Yesterday,Imagine,Let It Be라면 출력은 다음과 같습니다.
Playing: Yesterday
Playing: Imagine
Playing: Let It Be
Playlist complete!Main class가 기본 array 구조에 대해 아무것도 알지 못한 채 iterator의 hasNext() 및 next() 메서드를 사용하여 플레이리스트를 탐색하는 방식에 주목하세요. iterator가 모든 탐색 로직을 캡슐화하므로 컬렉션의 내부 표현이 client code에 노출되지 않습니다!
직접 해보기
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: 10개의 노래를 저장할 수 있는 용량의 Playlist 생성
// TODO: 입력(쉼표로 구분됨)을 파싱하여 각 노래 제목을 playlist에 추가
// TODO: createIterator()를 사용하여 playlist에서 이터레이터 가져오기
// TODO: 이터레이터를 사용하여 모든 노래 순회
// 각 노래를 Song 객체로 감싸서 출력
// TODO: Print "Playlist complete!" after iterating through all songs
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
4상속
상속의 기초 (extends)super 키워드메서드 오버라이딩 (@Override)생성자 체이닝Object 클래스단일 및 다중 레벨 상속다중 클래스 상속이 불가능한 이유요약 - 직원 계층 구조직접 연습해 보세요: 온라인 Java 컴파일러