cs Iterator and Registry

This commit is contained in:
Dominik Liebler 2013-09-21 22:17:54 +02:00
parent 4b66417509
commit 9484868299
7 changed files with 118 additions and 160 deletions

View File

@ -1,87 +0,0 @@
<?php
namespace DesignPatterns\Iterator;
/**
* Iterator provides a standard way to iterate over a collection without knowing
* how it is implemented. All you need to know is that you can traverse it
* with current, valid, next, rewind and key.
*
* That's the key feature of this pattern :
* The underlaying machinery could be an array, a matrix, a file, a cursor
* from database, a webservice with a cache, you don't care anymore.
*
* Note: This design pattern changes from one language to another. It depends
* mostly how loop statements handle collections (see Java before and after 1.5)
*
* In this simple example, I try to demonstrate how I manage a "linear" iterator
* on a card game but in fact, the underlaying storage is handled by two combined
* arrays.
*
* If tomorrow you decide to read cards from a database, the client
* (see the PHPUnit test) will remain unchanged. That's the beauty of it.
*/
class CardGame implements \Iterator
{
/**
* @var array
*/
protected $color = array('D', 'S', 'C', 'H');
/**
* @var array
*/
protected $number = array(7, 8, 9, 10, 'J', 'Q', 'K', 'A');
/**
* Return the current value
*
* @return string
*/
public function current()
{
return current($this->number) . ' of ' . current($this->color);
}
/**
* Return the current key
*
* @return string
*/
public function key()
{
return current($this->color) . current($this->number);
}
/**
* Go to the next item in the collection
*/
public function next()
{
if (false === next($this->number)) {
if (false !== next($this->color)) {
reset($this->number);
}
}
}
/**
* Go to the first item in the collection
*/
public function rewind()
{
reset($this->color);
reset($this->number);
}
/**
* Is the current position a valid item (true)
* or do we reach the end (false) ?
*
* @return boolean
*/
public function valid()
{
return current($this->number) || current($this->color);
}
}

51
Iterator/File.php Normal file
View File

@ -0,0 +1,51 @@
<?php
namespace DesignPatterns\Iterator;
/**
* iterator pattern
*
* Purpose:
* to make an object iterable
*
* Examples:
* - to process a file line by line by just running over all lines (which have an object representation) for a file
* (which of course is an object, too)
*
* Note:
* Standard PHP Library (SPL) defines an interface Iterator which is best suited for this!
* Often you would want to implement the Countable interface too, to allow count($object) on your iterable object
*
* 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();
}
}

27
Iterator/Row.php Normal file
View File

@ -0,0 +1,27 @@
<?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,53 +1,11 @@
<?php
namespace DesignPatterns;
namespace DesignPatterns\Iterator;
/**
* iterator pattern
*
* Purpose:
* to make an object iterable
*
* Examples:
* - to process a file line by line by just running over all lines (which have an object representation) for a file
* (which of course is an object, too)
*
* Note:
* Standard PHP Library (SPL) defines an interface Iterator which is best suited for this!
* Often you would want to implement the Countable interface too, to allow count($object) on your iterable object
*
* THIS EXAMPLE ALSO APPLIES THE COMPOSITE PATTERN
*
* Class RowSet
*/
class File
{
/**
* @var RowSet
*/
protected $rowSet;
/**
* @var string
*/
protected $pathName;
/**
* @param string $pathName
*/
public function __construct($pathName)
{
$this->rowSet = new Rowset($this);
}
public function process()
{
// this is the place to show how using an iterator, with foreach
// See the CardGame.php file
$this->rowSet->process();
}
}
class Rowset implements \Iterator
class RowSet implements \Iterator
{
/**
* @var
@ -59,6 +17,11 @@ class Rowset implements \Iterator
*/
protected $file;
/**
* @var int
*/
protected $lineNumber;
/**
* @param string $file
*/
@ -79,20 +42,26 @@ class Rowset implements \Iterator
* 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.
* 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
@ -104,34 +73,28 @@ class Rowset implements \Iterator
}
}
/**
* {@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;
}
}
class Row
{
protected $_data;
public function __construct($data)
{
$this->_data = $data;
}
public function process()
{
// do some fancy things here ...
return $this->lineNumber;
}
}

View File

@ -37,7 +37,7 @@ class Multiton
*
* @var array
*/
private static $_instances = array();
private static $instances = array();
/**
* should not be called from outside: private!
@ -53,15 +53,16 @@ class Multiton
* uses lazy initialization
*
* @param string $instanceName
*
* @return Multiton
*/
public static function getInstance($instanceName)
{
if ( ! array_key_exists($instanceName, self::$_instances)) {
self::$_instances[$instanceName] = new self();
if (!array_key_exists($instanceName, self::$instances)) {
self::$instances[$instanceName] = new self();
}
return self::$_instances[$instanceName];
return self::$instances[$instanceName];
}
/**

View File

@ -52,9 +52,3 @@ abstract class Registry
// typically there would be methods to check if a key has already been registered and so on ...
}
// while bootstrapping the application
Registry::set(Registry::LOGGER, new \StdClass());
// throughout the application
Registry::get(Registry::LOGGER)->log('foo');

9
Registry/index.php Normal file
View File

@ -0,0 +1,9 @@
<?php
use DesignPatterns\Registry;
// while bootstrapping the application
Registry::set(Registry::LOGGER, new \StdClass());
// throughout the application
Registry::get(Registry::LOGGER)->log('foo');