mirror of
https://github.com/DesignPatternsPHP/DesignPatternsPHP.git
synced 2025-06-04 13:04:54 +02:00
Behavioral\Iterator restructured
This commit is contained in:
parent
3e515daa0f
commit
d225a43de7
32
Behavioral/Iterator/Book.php
Normal file
32
Behavioral/Iterator/Book.php
Normal 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();
|
||||
}
|
||||
}
|
42
Behavioral/Iterator/BookList.php
Normal file
42
Behavioral/Iterator/BookList.php
Normal 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);
|
||||
}
|
||||
}
|
77
Behavioral/Iterator/BookListIterator.php
Normal file
77
Behavioral/Iterator/BookListIterator.php
Normal 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 >= 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 >= 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 >= 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 >= 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;
|
||||
}
|
||||
}
|
23
Behavioral/Iterator/BookListReverseIterator.php
Normal file
23
Behavioral/Iterator/BookListReverseIterator.php
Normal 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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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 ...
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
66
Behavioral/Iterator/Tests/IteratorTest.php
Normal file
66
Behavioral/Iterator/Tests/IteratorTest.php
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user