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.
Sfida
FacileCostruiamo 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 genericaIterator<T>con due metodi:hasNext(), che restituisce un booleano per indicare se ci sono altri elementi, enext(), che restituisce l'elemento successivo di tipo T.Playlist.java: Crea la classe aggregata che contiene i brani. La tuaPlaylistdovrebbe memorizzare i brani in un array String con capacità fissa (passata al costruttore) e tenere traccia di quanti brani sono stati aggiunti. Includi un metodoaddSong(String song)per aggiungere brani alla playlist.La tua Playlist deve avere un metodo
createIterator()che restituisce unIterator<String>. Implementalo creando una classe interna privata chiamataPlaylistIteratorche 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 classeSongche racchiude il titolo di un brano. Dovrebbe avere un costruttore che accetta il titolo (String), un metodogetTitle()e un metodotoString()che restituiscePlaying: [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
}
}
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
1Fondamenti della programmazione a oggetti
File esterniIntroduzione alla programmazione a oggettiClassi e oggettiLa parola chiave thisMetodiCampi (attributi)Metodo costruttoreSovraccarico dei costruttoriRipasso - Calcolatrice semplice4Ereditarietà
Ereditarietà di base (extends)La parola chiave superSovrascrittura dei metodi (@Override)Concatenamento dei costruttoriLa classe ObjectEreditarietà singola e multilivelloPerché non esiste l'ereditarietà multipla delle classiRiepilogo: gerarchia dei dipendenti7Metodi speciali e classe Object
Metodo toString()equals() e hashCode()Metodo clone()compareTo() e ComparableInterfaccia ComparatorRiepilogo - Ordinamento personalizzato2Modificatori di accesso e incapsulamento
Panoramica dei livelli di accessoMetodi getter e setterNascondimento delle informazioniLa parola chiave finalRiepilogo - Gestore di conti bancari5Polimorfismo
Nozioni di base sull'overloading dei metodiOverride dei metodi (a runtime)Upcasting e downcastingL'operatore instanceofClassi e metodi astrattiRiepilogo - Calcolatore di forme8Concetti avanzati di OOP
Composizione vs ereditarietàAggregazione vs composizioneClassi interne, annidate e anonimeEnum e metodi degli EnumRecord (Java 16+)Classi sealed (Java 17+)11Modelli di progettazione Parte 1
Introduzione ai modelli di progettazionePattern SingletonPattern FactoryPattern BuilderPattern ObserverPattern Strategy3Proprietà di classe e membri statici
Variabili di istanza e staticheMetodi staticiBlocchi staticiCostanti (static final)Riepilogo - Contatore e utility6Interfacce e classi astratte
Introduzione alle interfacceImplementazione delle interfacceImplementazione di più interfacceMetodi default e static nelle interfacceClassi astratte e interfacce a confrontoInterfacce funzionaliRiepilogo: sistema di pagamento9Tipi generici
Introduzione ai tipi genericiClassi genericheMetodi genericiParametri di tipo con limitiCaratteri jolly (?, extends, super)Riepilogo - Contenitore generico12Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositePattern IteratorEsercitati da solo: Compilatore Java online