Iterador
- Área: Patrones de Diseño
- Carácter del recurso: Recomendado
Descripción
Es un patrón define una interfaz que declara los métodos necesarios para acceder secuencialmente a un grupo de objetos de una colección.
Nombre
También conocido como Iterator, Cursor.
Clasificación
Motivación
Debemos de disponer de un medio para navegar por los datos de una lista sin exponer su estructura interna. Asi mismo, se debe recorrer la lista de varias maneras pero sin que esto signifique añadir operaciones a la lista por cada tipo de recorrido. En algunos casos nos interesa mantener varios recorridos simultáneamente.
El patrón Iterador permite hacer todo esto. La solución que propone es dar la responsabilidad de recorre la lista a un objeto Iterador. Este define una interfaz para acceder a los elementos de la lista.
Aplicabilidad
- Para acceder a la información de un agregado sin exponer su estructura interna.
- Se quiere permitir varios tipo de recorrido sobre un agregado.
- Proporcionar una interfaz uniforme para recorrer diferentes tipos de agregados.
Participantes
- Agregado: define la interfaz para crear un objeto Iterador.
- Iterador: define la interfaz para agregar y recorrer elementos.
- AgregadoConcreto: Implementa la interfaz para crear un objeto Iterador.
- IteradorConcreto: Implementa la interfaz de Iterador y mantiene la posición actual del recorrido.
Colaboraciones
Un IteradorConcreto guarda como pasa el objeto actual al siguiente del agregado.
Consecuencias
- Permite variaciones en el recorrido de un Agregado. Nuevos recorridos simplemente necesitan nuevas subclases de Iterador, si es una modificación solo es necesario cambiar la instancia de Iterador concreta
- Puede hacerse más de un recorrido a la vez sobre un Agregado.
- Los Iteradores simplifican la interfaz del contenedor
Implementación
Para una correcta implementación del patrón deben considerase las siguientes cuestiones:
- ¿Quién controla la iteración? Puede realizarse de forma externa a través del cliente o realizarlo de forma interna con el Iterador. En este caso, el Iterador recibe una función a aplicar sobre los elementos del Agregado y el recorrido es automático.
- ¿Quién define el algoritmo de recorrido? Se puede hacer en el Iterador o en el Agregado. Si es en el caso del Agregado, se implementa el método siguiente y se deja el Iterador para almacenar la posición actual. En el caso de realizarlo en el Iterador, los recorridos son más fáciles de implementar pero se compromete la encapsulación.
- ¿Cómo de robusto es el Iterador? Es recomendable formalizar un Iterador robusto que permita inserciones y borrados sin alterar el recorrido.
- Se pueden añadir operaciones adicionales al Iterador.
- Iteradores Nulos: Ayudan a manejar condiciones límite. El método Terminado() devuelve siempre True. Útil para estructuras heterogéneas
Código de ejemplo
import java.util.*;
class IntSet {
private Hashtable ht = new Hashtable();
// 1. Diseñamosun iterador interno
public static class Iterador {
private IntSet set;
private Enumeracion e;
private Integer actual;
public Iterador( IntSet in ) { set = in; }
public void primero() { e = set.ht.keys(); next(); }
public boolean realizado() { return actual == null; }
public int valorActual() { return actual.intValue(); }
public void next() {
try { actual = (Integer) e.nextElement(); }
catch (NoSuchElementException e) { actual = null; }
} }
public void add( int in ) { ht.put( new Integer( in ), "null" ); }
public boolean esMiembro( int i ) { return ht.containsKey(new Integer(i)); }
public Hashtable getHashtable() { return ht; }
// 2. Añadir un IteradorConcreto()
public Iterador crearIterador() { return new Iterador( this ); }
}
class IteradorDemo {
public static void main( String args ) {
IntSet set = new IntSet();
for (int i=2; i < 10; i += 2) set.add( i );
for (int i=1; i < 9; i++)
System.out.print( i + "-" + set.esMiembro( i ) + " " );
// Cliente va creando objetos iteradores
IntSet.Iterador it1 = set.crearIterador();
IntSet.Iterador it2 = set.crearIterador();
System.out.print( "\nIterator: " );
for ( it1.primero(), it2.primero(); ! it1.realizado(); it1.next(), it2.next() )
System.out.print( it1.valorActual() + " " + it2.valorActual() + " " );
// Java usa una collecion propia que la llammamos enumeracion
System.out.print( "\nEnumeracion: " );
for (Enumeration e = set.getHashtable().keys(); e.hasMoreElements(); )
System.out.print( e.nextElement() + " " );
System.out.println();
}
}
La salida sería:
1-false 2-true 3-false 4-true 5-false 6-true 7-false 8-true
Iterador: 8 8 6 6 4 4 2 2
Enumeracion: 8 6 4 2
Contenidos relacionados
Código | Título | Tipo | Carácter |
---|---|---|---|
RECU-0013 | Patrones de diseño | Ficha | Recomendado |
RECU-0184 | Composite | Patrón | Recomendado |
RECU-0195 | Memento | Patrón | Recomendado |