PHP Design Patterns .

PHP Design Patterns Iterator

About the Iterator

In the Iterator pattern a class will be able to traverse the elements of another class.

In this example, the BookList class will have stored zero to many elements of the Book class. The BookListIterator can return all of the Books in the BookList one by one and in the sequential order that the Book elements were added to the BookList.

I also show a BookListReverseIterator. The BookListReverseIterator can return all of the Books in the BookList one by one and in the reverse sequential order that the Book elements were added to the BookList. This is added to show that custom iterators can be quite useful when you need to process a list in an sequence other than sequentially first to last. While this Iterator is reverse, I could have also shown an iterator that returned, for example, only odd numbered elements.

Note that the Iterators shown are not "robust", and would yield unpredicatable results if the List the Iterator is processing has elements removed while the Iterator is traversing the List.


Book.php

//copyright Lawrence Truett and FluffyCat.com 2005, all rights reserved
  
  class Book {

private $author; private $title;

function __construct($title_in, $author_in) { $this->author = $author_in; $this->title = $title_in; }

function getAuthor() {return $this->author;}

function getTitle() {return $this->title;}

function getAuthorAndTitle() { return $this->getTitle() . ' by ' . $this->getAuthor(); }

}
To download source right-click here and "Save As...".

BookList.php

//copyright Lawrence Truett and FluffyCat.com 2005, all rights reserved

include_once('Book.php');

class BookList { private $books = array(); private $bookCount = 0;

public function __construct() { }

public function getBookCount() { return $this->bookCount; }

private function setBookCount($newCount) { $this->bookCount = $newCount; }

public function getBook($bookNumberToGet) { if ( (is_numeric($bookNumberToGet)) && ($bookNumberToGet <= $this->getBookCount())) { return $this->books[$bookNumberToGet]; } else { return NULL; } }

public function addBook(Book $book_in) { $this->setBookCount($this->getBookCount() + 1); $this->books[$this->getBookCount()] = $book_in; return $this->getBookCount(); }

public function removeBook(Book $book_in) { $counter = 0; while (++$counter <= $this->getBookCount()) { if ($book_in->getAuthorAndTitle() == $this->books[$counter]->getAuthorAndTitle()) { for ($x = $counter; $x < $this->getBookCount(); $x++) { $this->books[$x] = $this->books[$x + 1]; } $this->setBookCount($this->getBookCount() - 1); } } return $this->getBookCount(); }

}
To download source right-click here and "Save As...".

BookListIterator.php

//copyright Lawrence Truett and FluffyCat.com 2005, all rights reserved

include_once('Book.php'); include_once('BookList.php');

class BookListIterator { protected $bookList; protected $currentBook = 0;

public function __construct(BookList $bookList_in) { $this->bookList = $bookList_in; } public function getCurrentBook() { if (($this->currentBook > 0) && ($this->bookList->getBookCount() >= $this->currentBook)) { return $this->bookList->getBook($this->currentBook); } }

public function getNextBook() { if ($this->hasNextBook()) { return $this->bookList->getBook(++$this->currentBook); } else { return NULL; } }

public function hasNextBook() { if ($this->bookList->getBookCount() > $this->currentBook) { return TRUE; } else { return FALSE; } } }
To download source right-click here and "Save As...".

BookListReverseIterator.php

//copyright Lawrence Truett and FluffyCat.com 2005, all rights reserved

include_once('BookListIterator.php');

class BookListReverseIterator extends BookListIterator {

public function __construct(BookList $bookList_in) { $this->bookList = $bookList_in; $this->currentBook = $this->bookList->getBookCount() + 1; }

public function getNextBook() { if ($this->hasNextBook()) { return $this->bookList->getBook(--$this->currentBook); } else { return NULL; } }

public function hasNextBook() { if (1 < $this->currentBook) { return TRUE; } else { return FALSE; } } }
To download source right-click here and "Save As...".


testIterator.php

//copyright Lawrence Truett and FluffyCat.com 2005, all rights reserved

include_once('Book.php'); include_once('BookList.php'); include_once('BookListIterator.php'); include_once('BookListReverseIterator.php');

echo tagins("html"); echo tagins("head"); echo tagins("/head"); echo tagins("body");

echo "BEGIN TESTING ITERATOR PATTERN"; echo tagins("br").tagins("br"); $firstBook = new Book("Core PHP Programming, Third Edition", "Atkinson and Suraski"); $secondBook = new Book("PHP Bible", "Converse and Park"); $thirdBook = new Book("Design Patterns", "Gamma, Helm, Johnson, and Vlissides");

$books = new BookList(); $books->addBook($firstBook); $books->addBook($secondBook); $books->addBook($thirdBook); echo "Testing the Iterator".tagins("br"); $booksIterator = new BookListIterator($books);

while ($booksIterator->hasNextBook()) { $book = $booksIterator->getNextBook(); echo "getting next book with iterator : ".tagins("br"); echo $book->getAuthorAndTitle(); echo tagins("br").tagins("br"); } $book = $booksIterator->getCurrentBook(); echo "getting current book with iterator : ".tagins("br"); echo $book->getAuthorAndTitle(); echo tagins("br").tagins("br"); echo tagins("br"); echo "Testing the Reverse Iterator".tagins("br");

$booksReverseIterator = new BookListReverseIterator($books);

while ($booksReverseIterator->hasNextBook()) { $book = $booksReverseIterator->getNextBook(); echo "getting next book with reverse iterator : ".tagins("br"); echo $book->getAuthorAndTitle(); echo tagins("br").tagins("br"); } $book = $booksReverseIterator->getCurrentBook(); echo "getting current book with reverse iterator : ".tagins("br"); echo $book->getAuthorAndTitle(); echo tagins("br").tagins("br");

echo tagins("br"); echo "END TESTING ITERATOR PATTERN"; echo tagins("br"); echo tagins("/body"); echo tagins("/html"); //doing this so code can be displayed without breaks function tagins($stuffing) { return "<".$stuffing.">"; }
To download source right-click here and "Save As...".

output of testDecorator.php

BEGIN TESTING ITERATOR PATTERN

Testing the Iterator getting next book with iterator : Core PHP Programming, Third Edition by Atkinson and Suraski

getting next book with iterator : PHP Bible by Converse and Park

getting next book with iterator : Design Patterns by Gamma, Helm, Johnson, and Vlissides

getting current book with iterator : Design Patterns by Gamma, Helm, Johnson, and Vlissides

Testing the Reverse Iterator getting next book with reverse iterator : Design Patterns by Gamma, Helm, Johnson, and Vlissides

getting next book with reverse iterator : PHP Bible by Converse and Park

getting next book with reverse iterator : Core PHP Programming, Third Edition by Atkinson and Suraski

getting current book with reverse iterator : Core PHP Programming, Third Edition by Atkinson and Suraski

END TESTING ITERATOR PATTERN

References


Design Patterns
Design Patterns by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides

PHP 5
The Official PHP web site
Core PHP Programming, 3rd Edition by Leon Atkinson and Zeev Suraski
Comments
Sign in to be the first to comment on PHP Design Patterns Iterator.