mirror of
https://github.com/DesignPatternsPHP/DesignPatternsPHP.git
synced 2025-02-24 01:32:22 +01:00
cs Iterator and Registry
This commit is contained in:
parent
4b66417509
commit
9484868299
@ -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
51
Iterator/File.php
Normal 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
27
Iterator/Row.php
Normal 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 ...
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
9
Registry/index.php
Normal 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');
|
Loading…
x
Reference in New Issue
Block a user