Design patterns: Iterator
L’Iterator Pattern è un design pattern comportamentale che fornisce un modo per accedere sequenzialmente agli elementi di una collezione senza esporre la sua rappresentazione interna. Questo pattern separa la logica di iterazione dalla collezione, consentendo di attraversare una struttura dati in modo trasparente e flessibile, indipendentemente dalla sua implementazione sottostante.
Punti di Forza
- Separazione delle Responsabilità: L’Iterator Pattern separa il codice che gestisce la struttura dati da quello che attraversa la collezione. Questo semplifica la manutenibilità e migliora la leggibilità del codice.
- Uniformità di Accesso; Fornisce un’interfaccia uniforme per attraversare diverse strutture dati, rendendo il codice client indipendente dalla rappresentazione interna della collezione.
- Facilità di Sostituzione della Struttura Dati: Il pattern facilita il cambio della struttura dati sottostante (array, lista, set, ecc.) senza dover modificare il codice client che utilizza l’iteratore.
- Flessibilità e Riutilizzo: Aggiungere o modificare il comportamento di un iteratore (ad esempio, per un filtro o un’iterazione inversa) è semplice e non richiede modifiche alla collezione originale.
- Compatibilità con il Principio di Singola Responsabilità: Con l’Iterator Pattern, la logica di iterazione viene delegata a un iteratore dedicato, permettendo alla collezione di concentrarsi sulla gestione dei dati e migliorando il design del codice.
Caso d’uso: Collezione di Libri
Immaginiamo di avere una collezione di libri e vogliamo poter iterare su di essa senza esporre i dettagli interni della sua implementazione.
Codice PHP
// Definisce l'interfaccia per l'iteratore
interface Iterator {
public function hasNext(): bool;
public function next();
}
// Collezione di libri
class BookCollection {
private $books = [];
public function addBook($book) {
$this->books[] = $book;
}
public function createIterator(): Iterator {
return new BookIterator($this->books);
}
}
// Implementazione dell'iteratore per la collezione di libri
class BookIterator implements Iterator {
private $books;
private $position = 0;
public function __construct($books) {
$this->books = $books;
}
public function hasNext(): bool {
return $this->position < count($this->books);
}
public function next() {
return $this->books[$this->position++];
}
}
// Caso d'uso
$collection = new BookCollection();
$collection->addBook("The Catcher in the Rye");
$collection->addBook("To Kill a Mockingbird");
$collection->addBook("1984");
// Utilizzo dell'iteratore per attraversare la collezione
$iterator = $collection->createIterator();
while ($iterator->hasNext()) {
echo $iterator->next() . PHP_EOL;
}
Spiegazione
- Interfaccia Iterator: Definisce i metodi standard che un iteratore deve implementare (hasNext() e next()).
- Classe BookCollection: Contiene la collezione di libri e un metodo createIterator per restituire un iteratore.
- Classe BookIterator: Implementa l’interfaccia Iterator e fornisce il meccanismo per attraversare la collezione di libri.
- Utilizzo: Creiamo una collezione di libri, aggiungiamo alcuni libri, e utilizziamo l’iteratore per iterare sugli elementi della collezione senza accedere direttamente alla struttura interna.
Conclusione
L’Iterator Pattern offre un modo flessibile per attraversare collezioni complesse, migliorando la manutenibilità del codice e la separazione delle responsabilità. È ideale quando la struttura dati può cambiare o quando si vuole nascondere la logica di attraversamento al codice client.