🚨 ¡Nueva review! ¡Mi teclado ideal! ⌨️ Perfecto para programar, el Logitech MX Keys S . ¡Échale un ojo! 👀

El Patrón de diseño Iterator

Recorre tus colecciones sin saber cómo están hechas por dentro.

Escrito por domin el 24 de noviembre de 2025

🔄 El Patrón Iterator: El Mando a Distancia Universal

El Patrón Iterator (Iterador) es probablemente el patrón de diseño que más usas sin darte cuenta (foreach, ¿te suena?). Su objetivo es permitir recorrer los elementos de una colección sin exponer lo que está por debajo (lista, pila, árbol, etc.).

El problema que resuelve es este:
¿Cómo puedes acceder a los elementos de una colección compleja de forma secuencial sin tener que conocer y acoplarte a su estructura interna?

La respuesta es extraer la lógica de recorrido a un objeto separado llamado Iterador.

Diagrama del Patrón Iterator.

📺 1. Un ejemplo sencillo: El mando de la tele

Imagina que tienes una televisión (la colección):

Concepto (Analogía)

Rol en Iterator

Tarea Principal

Televisión

Agregado (Colección)

Contiene los datos reales y crea el iterador.

Mando a Distancia

Iterador

Lleva la cuenta de la posición actual y sabe cómo avanzar.

🛠️ 2. Los tres pilares del patrón Iterator

1. Interfaz iterador

2. Iterador concreto

3. Interfaz agregado (colección)

🤔 1. ¿Qué ventaja tiene separar la lógica de iteración de la propia colección?

🎵 3. El ejemplo clásico: Playlist de Spotify

Tienes una lista de canciones. Puedes querer recorrerla:

  1. En orden normal (1, 2, 3…).
  2. En modo aleatorio (Shuffle).
  3. Por artista.

En lugar de llenar la clase Playlist con métodos getSiguienteRandom(), getSiguientePorArtista(), creas distintos iteradores (IteradorAleatorio, IteradorSecuencial).

🤔 2. En PHP, ¿qué interfaz nativa facilita la implementación de este patrón?

✅ 4. ¿Por Qué Usarlo?

  1. Principio de Responsabilidad Única: Limpias tus clases de colección de algoritmos de recorrido complejos.
  2. Intercambiabilidad: Puedes cambiar la forma de recorrer los datos sin cambiar el código que los usa.
  3. Uniformidad: Usas la misma interfaz para recorrer arrays, árboles, listas enlazadas, etc.

❌ 5. Desventaja a Considerar

🤔 3. ¿Puede un iterador modificar la colección mientras la recorre?

💡 6. Conclusión

El Iterator es fundamental para escribir algoritmos genéricos que funcionen con cualquier tipo de colección. Te da la libertad de cambiar cómo guardas los datos sin romper el código que los lee.

🧠 7. Ejemplo Práctico en PHP

Vamos a crear un iterador personalizado para una colección de palabras.

<?php

// 🔹 1. Interfaz Iterador (Simplificada)
interface IteradorPersonalizado
{
    public function tieneSiguiente(): bool;
    public function siguiente();
}

// 🔹 2. Colección Concreta
class ColeccionPalabras
{
    private array $items = [];

    public function agregar(string $item): void
    {
        $this->items[] = $item;
    }

    public function getItems(): array
    {
        return $this->items;
    }

    public function getIterador(): IteradorPersonalizado
    {
        return new IteradorOrdenAlfabetico($this);
    }
}

// 🔹 3. Iterador Concreto
class IteradorOrdenAlfabetico implements IteradorPersonalizado
{
    private ColeccionPalabras $coleccion;
    private int $posicion = 0;
    private array $cacheOrdenada;

    public function __construct(ColeccionPalabras $coleccion)
    {
        $this->coleccion = $coleccion;
        // Copiamos y ordenamos los datos para iterar alfabéticamente
        $this->cacheOrdenada = $coleccion->getItems();
        sort($this->cacheOrdenada);
    }

    public function tieneSiguiente(): bool
    {
        return isset($this->cacheOrdenada[$this->posicion]);
    }

    public function siguiente()
    {
        $item = $this->cacheOrdenada[$this->posicion];
        $this->posicion++;
        return $item;
    }
}

// 🔹 4. Uso
$coleccion = new ColeccionPalabras();
$coleccion->agregar("Zanahoria");
$coleccion->agregar("Arroz");
$coleccion->agregar("Manzana");

$iterador = $coleccion->getIterador();

echo "--- Lista de la compra ordenada ---\n";
while ($iterador->tieneSiguiente()) {
    echo "• " . $iterador->siguiente() . "\n";
}

// 🖥️ Salida:
// --- Lista de la compra ordenada ---
// • Arroz
// • Manzana
// • Zanahoria

EA, ¡saluditos y nos vemos en los bares! 🍻