Padrão Iterator
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy. Lição 76 de 87.
O Padrão Iterator é um padrão de projeto comportamental que oferece uma maneira de acessar os elementos de uma coleção sequencialmente, sem expor sua estrutura subjacente. Seja trabalhando com um array, uma lista encadeada ou uma árvore, o iterador oferece uma maneira uniforme de percorrer os elementos.
O padrão separa a lógica de percurso da própria coleção. Ele envolve dois componentes principais: uma interface de Iterador que define métodos para percorrer elementos e um Iterável (ou Agregado) que cria iteradores para sua coleção:
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++];
}
}
}O iterador mantém seu próprio estado de percurso, permitindo que vários iteradores percorram a mesma coleção de forma independente. Os clientes usam o iterador sem saber como a coleção armazena seus dados:
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());
}As interfaces integradas Iterable e Iterator do Java seguem exatamente esse padrão, e é por isso que você pode usar loops for aprimorados com qualquer classe que implemente Iterable. O Padrão Iterator é essencial quando você precisa fornecer vários métodos de travessia ou ocultar estruturas internas complexas do código cliente.
Desafio
FácilVamos criar um sistema de playlists usando o padrão Iterator! Você criará uma playlist de músicas que armazena músicas e fornece um iterador personalizado para percorrê-las em sequência, sem expor como as músicas são armazenadas internamente. Este é um caso de uso perfeito para o padrão Iterator, permitindo que os usuários naveguem pela sua coleção por meio de uma interface simples e uniforme.
Você organizará seu código em quatro arquivos:
Iterator.java: Defina sua interface genéricaIterator<T>com dois métodos:hasNext(), que retorna um booleano indicando se há mais elementos, enext(), que retorna o próximo elemento do tipo T.Playlist.java: Crie a classe agregadora que contém suas músicas. SuaPlaylistdeve armazenar músicas em um array de String com capacidade fixa (passada ao construtor) e acompanhar quantas músicas foram adicionadas. Inclua um métodoaddSong(String song)para adicionar músicas à playlist.Sua Playlist precisa de um método
createIterator()que retorna umIterator<String>. Implemente-o criando uma classe interna privada chamadaPlaylistIteratorque implementa sua interface Iterator. Esse iterador interno mantém sua própria posição de índice e percorre o array de músicas, retornando cada música na ordem.Song.java: Crie uma classe simplesSongque encapsula o título de uma música. Ela deve ter um construtor que recebe o título (String), um métodogetTitle()e um métodotoString()que retornaPlaying: [title].Main.java: Junte seu sistema de iteradores! Você receberá uma entrada: uma lista de títulos de músicas separados por vírgulas (por exemplo:Bohemian Rhapsody,Stairway to Heaven,Hotel California).Crie uma Playlist com capacidade para 10 músicas. Analise a entrada e adicione cada título de música à playlist. Em seguida, obtenha um iterador da playlist e use-o para percorrer todas as músicas, imprimindo cada uma encapsulada em um objeto Song (que será exibido como
Playing: [title]).Depois de percorrer todas as músicas, imprima
Playlist complete!em uma nova linha.
Você receberá uma entrada: uma string com títulos de músicas separados por vírgulas.
Por exemplo, com a entrada Yesterday,Imagine,Let It Be, sua saída seria:
Playing: Yesterday
Playing: Imagine
Playing: Let It Be
Playlist complete!Observe como sua classe Main usa os métodos hasNext() e next() do iterador para percorrer a playlist sem saber nada sobre a estrutura do array subjacente. O iterador encapsula toda a lógica de percurso, mantendo a representação interna da coleção oculta do código cliente!
Experimente você mesmo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: Crie uma Playlist com capacidade para 10 músicas
// TODO: Analise a entrada (separada por vírgulas) e adicione cada título de música à playlist
// TODO: Obtenha um iterador da playlist usando createIterator()
// TODO: Use o iterador para percorrer todas as músicas
// Para cada música, encapsule-a em um objeto Song e imprima-o
// TODO: Imprima "Playlist complete!" após percorrer todas as músicas
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão IteratorPratique por conta própria: Compilador de Java online