Dzisiaj trochę na temat wzorca Iterator. Służy on do zapewnienia zunifikowanego dostępu do elementów obiektu. Najważniejsze o co w tym wzorcu chodzi to „bez ujawniania jego implementacji wewnętrznej”.

Często w programowaniu ten sam rezultat możemy uzyskać przy pomocy paru technik, te same dane możemy przechowywać w pamięci w różny sposób. Przy użyciu tablic, list lub innych struktur.

Jeżeli nie oddzielimy od siebie przechowywania i sposobu dostępu do danych, to każda zmiana w środku wymagać będzie zmiany w innych miejscach aplikacji. Taki zunifikowany interfejs dostępu pozwala na uniwersalne przetwarzanie poszczególnych kolekcji danych oraz separację części kodu.

W PHP i Javie mamy wbudowane interfejsy iteratorów i agregatorów, które pozwalają na używanie różnych danych w standardowych pętlach typu „foreach” w PHP jest to interfejs Iterator , w Java – interfejs Iterator

Przykładowa implementacja, bardzo prosta, żeby zrozumieć o co chodzi:

package pl.shad.net.blog;

import java.util.ArrayList;
import java.util.List;

/**
 * Interfejs wzorca iteraotr
 */
interface Iterator< E >{
    boolean hasNext();
    E next();
}

/**
 * Klasa obsługująca dostęp do danych zawartych w tablicy
 */
class ArrayIterator< E > implements Iterator{

    int posistion = 0;
    E[] items;

    public ArrayIterator(E[] items){
        this.items = items;
    }

    @Override
    public boolean hasNext(){
        if (posistion >= items.length || items[posistion] == null){
            return false;
        }
        return true;
    }

    @Override
    public E next(){
        E item = items[posistion];
        posistion++;
        return item;
    }
}

/**
 * Klasa obsługująca dostęp do danych zawartych w liście
 */
class ListIterator< E > implements Iterator{

    int posistion = 0;
    List< E > items;

    public ListIterator(List< E > items){
        this.items = items;
    }

    @Override
    public boolean hasNext(){
        if (posistion >= items.size() || items.get(posistion) == null){
            return false;
        }
        return true;
    }

    @Override
    public E next(){
        E item = items.get(posistion);
        posistion++;
        return item;
    }
}

/**
 * Testowanie działania wzorca iterator
 */
public class DesignPatternsIterator{

    private static Integer[] intArray = new Integer[10];
    private static ArrayList< Integer > intList = new ArrayList< Integer >();

    public static void main(String[] args){

        //
        // Dodanie danych do tablicy
        //
        intArray[0] = 1;
        intArray[1] = 11;
        intArray[2] = 21;
        intArray[3] = 31;
        intArray[4] = 41;
        intArray[5] = 51;
        intArray[6] = 61;
        intArray[7] = 71;
        intArray[8] = 81;
        intArray[9] = 91;

        //
        // Dodanie danych do listy
        //
        intList.add(1);
        intList.add(11);
        intList.add(21);
        intList.add(31);
        intList.add(41);
        intList.add(51);
        intList.add(61);
        intList.add(71);
        intList.add(81);

        //
        // Wyświetlanie zawartości przy pomocy iteratora
        // metoda wymaga klas implementujących interfejs iterator,
        // który zapewnia usystematyzowany dostęp do danych
        //
        printData(new ArrayIterator(intArray), "Tablica");
        printData(new ListIterator(intList), "Lista");
    }

    /**
     * Drukowanie zawartości kolekcji
     *
     * @param iterator
     * @param info
     */
    private static void printData(Iterator iterator, String info){

        if (iterator != null){

            System.out.println("Dane: " + info);
            while (iterator.hasNext()){
                System.out.print(iterator.next() + ", ");
            }
            System.out.println("");
            System.out.println("");
        }
    }
}