Behavioral\Iterator restructured

This commit is contained in:
Antonio Spinelli 2014-03-24 10:40:08 -03:00
parent 3e515daa0f
commit d225a43de7
8 changed files with 240 additions and 166 deletions

View File

@ -0,0 +1,32 @@
<?php
namespace DesignPatterns\Behavioral\Iterator;
class Book
{
private $author;
private $title;
public function __construct($title, $author)
{
$this->author = $author;
$this->title = $title;
}
public function getAuthor()
{
return $this->author;
}
public function getTitle()
{
return $this->title;
}
public function getAuthorAndTitle()
{
return $this->getTitle() . ' by ' . $this->getAuthor();
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace DesignPatterns\Behavioral\Iterator;
class BookList implements \Countable
{
private $books;
public function getBook($bookNumberToGet)
{
if ((int)$bookNumberToGet <= $this->count()) {
return $this->books[$bookNumberToGet];
}
return NULL;
}
public function addBook(Book $book)
{
$this->books[] = $book;
return $this->count();
}
public function removeBook(Book $bookToRemove)
{
foreach ($this as $key => $book) {
/** @var Book $book */
if ($book->getAuthorAndTitle() === $bookToRemove->getAuthorAndTitle()) {
unset($this->books[$key]);
}
}
return $this->count();
}
public function count()
{
return count($this->books);
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace DesignPatterns\Behavioral\Iterator;
class BookListIterator implements \Iterator
{
/**
* @var BookList
*/
protected $bookList;
/**
* @var int
*/
protected $currentBook = 0;
public function __construct(BookList $bookList)
{
$this->bookList = $bookList;
}
/**
* Return the current book
* @link http://php.net/manual/en/iterator.current.php
* @return Book Can return any type.
*/
public function current()
{
return $this->bookList->getBook($this->currentBook);
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Move forward to next element
* @link http://php.net/manual/en/iterator.next.php
* @return void Any returned value is ignored.
*/
public function next()
{
$this->currentBook++;
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Return the key of the current element
* @link http://php.net/manual/en/iterator.key.php
* @return mixed scalar on success, or null on failure.
*/
public function key()
{
return $this->currentBook;
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Checks if current position is valid
* @link http://php.net/manual/en/iterator.valid.php
* @return boolean The return value will be casted to boolean and then evaluated.
* Returns true on success or false on failure.
*/
public function valid()
{
return $this->currentBook < $this->bookList->count();
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Rewind the Iterator to the first element
* @link http://php.net/manual/en/iterator.rewind.php
* @return void Any returned value is ignored.
*/
public function rewind()
{
$this->currentBook = 0;
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace DesignPatterns\Behavioral\Iterator;
class BookListReverseIterator extends BookListIterator
{
public function __construct(BookList $bookList)
{
$this->bookList = $bookList;
$this->currentBook = $this->bookList->count() - 1;
}
public function next()
{
$this->currentBook--;
}
public function valid()
{
return 0 <= $this->currentBook;
}
}

View File

@ -1,39 +0,0 @@
<?php
namespace DesignPatterns\Iterator;
/**
* class File
*
* THIS EXAMPLE ALSO APPLIES THE COMPOSITE PATTERN
*/
class File
{
/**
* @var RowSet
*/
protected $rowSet;
/**
* @var string
*/
protected $pathName;
/**
* @param string $pathName
*/
public function __construct($pathName)
{
$this->rowSet = new Rowset($this);
}
/**
* processes the rowSet
*/
public function process()
{
// this is the place to show how using an iterator, with foreach
// See the CardGame.php file
$this->rowSet->process();
}
}

View File

@ -1,27 +0,0 @@
<?php
namespace DesignPatterns\Iterator;
/**
* Class Row
*/
class Row
{
protected $data;
/**
* {@inheritdoc}
*/
public function __construct($data)
{
$this->data = $data;
}
/**
* {@inheritdoc}
*/
public function process()
{
// do some fancy things here ...
}
}

View File

@ -1,100 +0,0 @@
<?php
namespace DesignPatterns\Iterator;
/**
* Class RowSet
*/
class RowSet implements \Iterator
{
/**
* @var
*/
protected $currentRow;
/**
* @var string
*/
protected $file;
/**
* @var int
*/
protected $lineNumber;
/**
* @param string $file
*/
public function __construct($file)
{
$this->file = $file;
}
/**
* composite pattern: run through all rows and process them
*
* @return void
*/
public function process()
{
// this actually calls rewind(), { next(), valid(), key() and current() :}
/**
* THE key feature of the Iterator Pattern is to provide a *public contract*
* to iterate on a collection without knowing how items are handled inside
* the collection. It is not just an easy way to use "foreach"
*
* One cannot see the point of iterator pattern if you iterate on $this.
* This example is unclear and mixed with some Composite pattern ideas.
*/
foreach ($this as $line => $row) {
$row->process();
}
}
/**
* {@inheritdoc}
*/
public function rewind()
{
// seek to first line from $this->file
}
/**
* {@inheritdoc}
*/
public function next()
{
// read the next line from $this->file
if (!$eof) {
$data = ''; // get the line
$this->currentRow = new Row($data);
} else {
$this->currentRow = null;
}
}
/**
* {@inheritdoc}
*/
public function current()
{
return $this->currentRow;
}
/**
* {@inheritdoc}
*/
public function valid()
{
return null !== $this->currentRow;
}
/**
* {@inheritdoc}
*/
public function key()
{
// you would want to increment this in next() or whatsoever
return $this->lineNumber;
}
}

View File

@ -0,0 +1,66 @@
<?php
namespace DesignPatterns\Behavioral\Iterator\Tests;
use DesignPatterns\Behavioral\Iterator\Book;
use DesignPatterns\Behavioral\Iterator\BookList;
use DesignPatterns\Behavioral\Iterator\BookListIterator;
use DesignPatterns\Behavioral\Iterator\BookListReverseIterator;
class IteratorTest extends \PHPUnit_Framework_TestCase
{
/**
* @var BookList
*/
protected $bookList;
protected function setUp()
{
$this->bookList = new BookList();
$this->bookList->addBook(new Book('Learning PHP Design Patterns', 'William Sanders'));
$this->bookList->addBook(new Book('Professional Php Design Patterns', 'Aaron Saray'));
$this->bookList->addBook(new Book('Clean Code', 'Robert C. Martin'));
}
public function expectedAuthors()
{
return array(
array(
array(
'Learning PHP Design Patterns by William Sanders',
'Professional Php Design Patterns by Aaron Saray',
'Clean Code by Robert C. Martin'
)
),
);
}
/**
* @dataProvider expectedAuthors
*/
public function testUseAIteratorAndValidateAuthors($expected)
{
$iterator = new BookListIterator($this->bookList);
while ($iterator->valid()) {
$expectedBook = array_shift($expected);
$this->assertEquals($expectedBook, $iterator->current()->getAuthorAndTitle());
$iterator->next();
}
}
/**
* @dataProvider expectedAuthors
*/
public function testUseAReverseIteratorAndValidateAuthors($expected)
{
$iterator = new BookListReverseIterator($this->bookList);
while ($iterator->valid()) {
$expectedBook = array_pop($expected);
$this->assertEquals($expectedBook, $iterator->current()->getAuthorAndTitle());
$iterator->next();
}
}
}