Iterator Pattern

The pattern allows:

  • for access to the elements of an aggregate object without allowing access to its underlying representation;
  • a uniform interface for traversal.

Iterator Pattern


With the Iterator pattern users can traverse various types of data sets without worrying about the underlying implementation of the collection.

PHP Example

PHP already comprises Iterator interface. Besides, SPL contains a set of extensible Iterator implementers. Here in the example I'm just using one of them.

<?php
/*
 * @category Design Pattern Tutorial
 * @package Iterator Sample
 * @author Dmitry Sheiko <me@dsheiko.com>
 * @link http://dsheiko.com
 */
class Dao_News
{
    public function fetchAll()
    {
        $raws = array(
            (object)array("id" => 1, "title" => "Title 1"),
            (object)array("id" => 2, "title" => "Title 2"),
            (object)array("id" => 3, "title" => "Title 3"),
        );
        return new ArrayIterator($raws);
    }
}
/**
 * Usage
 */
$dao = new Dao_News();
$newIt = $dao->fetchAll();
for ($newIt->rewind(); $newIt->valid(); $newIt->next()) {
    echo $newIt->current()->title, "\n";
}

// Output:
// Title 1
// Title 2
// Title 3

JS/ES5 Example

/*
 * @category Design Pattern Tutorial
 * @package Iterator Sample
 * @author Dmitry Sheiko <me@dsheiko.com>
 * @link http://dsheiko.com
 */
(function() {

var ArrayIterator = function(data) {
    var _key = 0,
        _valid = !!data.length;

    return {
        next: function() {
            var max = data.length - 1;
            _valid = _key < max ? !!(++_key) : false;
        },
        rewind: function() {
            _valid = !!data.length;
            _key = 0;
        },
        valid: function() {
            return _valid;
        },
        current: function() {
            return data[_key];
        },
        key: function() {
            return _key;
        }
    };
};
/**
 * Usage
 */
var it = new ArrayIterator(["first", "second", "third"]);
for (it.rewind(); it.valid(); it.next()) {
    console.log(it.current());
}
// Output:
// first
// second
// third

}());