Menu
Coddy logo textTech

Pattern Iterator

Fa parte della sezione Programmazione orientata agli oggetti del percorso Java di Coddy. Lezione 76 di 87.

Il Pattern Iterator è un pattern di progettazione comportamentale che offre un modo per accedere in sequenza agli elementi di una collezione senza esporne la struttura sottostante. Che tu stia lavorando con un array, una lista concatenata o un albero, l'iteratore ti offre un modo uniforme per attraversarne gli elementi.

Il pattern separa la logica di attraversamento dalla collezione stessa. Coinvolge due componenti principali: un'interfaccia Iterator che definisce i metodi per attraversare gli elementi e un Iterable (o Aggregate) che crea iteratori per la propria collezione:

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++];
        }
    }
}

L’iteratore mantiene il proprio stato di attraversamento, consentendo a più iteratori di attraversare la stessa raccolta in modo indipendente. I client utilizzano l’iteratore senza sapere come la raccolta memorizza i propri dati:

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());
}

Le interfacce integrate di Java Iterable e Iterator seguono esattamente questo schema, ed è per questo che puoi usare i cicli for potenziati con qualsiasi classe che implementi Iterable. Il pattern Iterator è essenziale quando devi fornire più metodi di attraversamento o nascondere strutture interne complesse al codice client.

challenge icon

Sfida

Facile

Costruiamo un sistema di playlist usando l'Iterator Pattern! Creerai una playlist musicale che memorizza brani e fornisce un iteratore personalizzato per attraversarli in sequenza, senza esporre il modo in cui sono memorizzati internamente. È un caso d'uso perfetto per l'Iterator Pattern, che consente agli utenti di navigare nella tua raccolta tramite un'interfaccia semplice e uniforme.

Organizzerai il codice in quattro file:

  • Iterator.java: Definisci l'interfaccia generica Iterator<T> con due metodi: hasNext(), che restituisce un booleano per indicare se ci sono altri elementi, e next(), che restituisce l'elemento successivo di tipo T.
  • Playlist.java: Crea la classe aggregata che contiene i brani. La tua Playlist dovrebbe memorizzare i brani in un array String con capacità fissa (passata al costruttore) e tenere traccia di quanti brani sono stati aggiunti. Includi un metodo addSong(String song) per aggiungere brani alla playlist.

    La tua Playlist deve avere un metodo createIterator() che restituisce un Iterator<String>. Implementalo creando una classe interna privata chiamata PlaylistIterator che implementa la tua interfaccia Iterator. Questo iteratore interno mantiene una propria posizione nell'indice e attraversa l'array dei brani, restituendo ciascun brano in ordine.

  • Song.java: Crea una semplice classe Song che racchiude il titolo di un brano. Dovrebbe avere un costruttore che accetta il titolo (String), un metodo getTitle() e un metodo toString() che restituisce Playing: [title].
  • Main.java: Metti insieme il tuo sistema di iteratori! Riceverai un input: un elenco di titoli di brani separati da virgole (ad esempio: Bohemian Rhapsody,Stairway to Heaven,Hotel California).

    Crea una Playlist con capacità pari a 10 brani. Analizza l'input e aggiungi ciascun titolo alla playlist. Poi ottieni un iteratore dalla playlist e usalo per attraversare tutti i brani, stampando ciascuno racchiuso in un oggetto Song (che verrà visualizzato come Playing: [title]).

    Dopo aver attraversato tutti i brani, stampa Playlist complete! su una nuova riga.

Riceverai un input: una stringa con titoli di brani separati da virgole.

Ad esempio, con l'input Yesterday,Imagine,Let It Be, il tuo output sarà:

Playing: Yesterday
Playing: Imagine
Playing: Let It Be
Playlist complete!

Nota come la tua classe Main usa i metodi hasNext() e next() dell'iteratore per attraversare la playlist senza conoscere nulla della struttura dell'array sottostante. L'iteratore incapsula tutta la logica di attraversamento, mantenendo nascosta al codice client la rappresentazione interna della raccolta!

Provalo tu

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        
        // TODO: Crea una Playlist con una capacità di 10 canzoni
        
        // TODO: Analizza l'input (separato da virgole) e aggiungi ogni titolo di canzone alla playlist
        
        // TODO: Ottieni un iteratore dalla playlist usando createIterator()
        
        // TODO: Usa l'iteratore per scorrere tutte le canzoni
        // Per ogni canzone, racchiudila in un oggetto Song e stampala
        
        // TODO: Stampa "Playlist complete!" dopo aver scorso tutte le canzoni
    }
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Java online