PHP教學-設計模式之迭代器模式(Iterator)
迭代器模式為聚合物件的元素提供一種順序訪問的方式,又能讓訪問者不必關心聚合物件內部的內部實現。實際上我們平常使用最多的陣列foreach操作就是在使用迭代器(注意:迭代器並不等於迭代器模式)。從PHP 5.3開始,PHP開始內置了Iterator介面,為我們實現迭代器模式提供了便利:
//PHP5提供的Iterator介面,Traversable介面只是為了標識物件是否可以通過foreach迭代,不包含任何方法
Iterator extends Traversable {
/* Methods */
abstract public mixed current ( void )
abstract public scalar key ( void )
abstract public void next ( void )
abstract public void rewind ( void )
abstract public boolean valid ( void )
}
也許你會覺得很奇怪(或多餘),對於PHP來說,陣列本身就是支持迭代的,我們為什麼還要通過迭代器模式多封裝一層呢?這就是模式定義的核心所在了:讓訪問者不必關心聚合物件的內部實現(比如元素數量、KEY、具體結構等);相對來說就是讓聚合物件的內部實現不暴露給訪問者(例如避免物件被訪問者修改)。
實現我們自己的迭代器:
class RecordIterator implements Iterator{
private $position = 0;
//注意:被迭代物件屬性是私有的
private $records = array();
public function __construct(Array $records) {
$this->position = 0;
$this->records = $records;
}
function rewind() {
$this->position = 0;
}
function current() {
return $this->records[$this->position];
}
function key() {
return $this->position;
}
function next() {
++$this->position;
}
function valid() {
return isset($this->records[$this->position]);
}
}
//假如我們從MongoDB中讀取得到下列資料
$data = array(
0 => array('field' => 'value'),
1 => array('field' => 'value'),
2 => array('field' => 'value'),
3 => array('field' => 'value'),
);
//使用我們自己定義的迭代器
$records = new RecordIterator($data);
while($records->valid()){
print_r($records->current());
$records->next();
}
$records->rewind();
在GoF定義的迭代器模式中,還有兩個參與者:容器和具體容器,負責初始化並返回具體的迭代器。
//容器
interface Aggregate
{
public getIterator();
}
//具體容器
class RecordList implements Aggregate{
private $iterator;
public function __construct($data){
$this->iterator = new RecordIterator($data);
}
public function getIterator(){
return $this->iterator;
}
}
//使用
//假如我們從MongoDB中讀取得到下列資料
$data = array(
0 => array('field' => 'value'),
1 => array('field' => 'value'),
2 => array('field' => 'value'),
3 => array('field' => 'value'),
);
$recordList = new RecordList($data);
$iterator = $recordList->getIterator();
while($iterator->valid()){
print_r($iterator->current());
$iterator->next();
}
//PHP5提供的Iterator介面,Traversable介面只是為了標識物件是否可以通過foreach迭代,不包含任何方法
Iterator extends Traversable {
/* Methods */
abstract public mixed current ( void )
abstract public scalar key ( void )
abstract public void next ( void )
abstract public void rewind ( void )
abstract public boolean valid ( void )
}
也許你會覺得很奇怪(或多餘),對於PHP來說,陣列本身就是支持迭代的,我們為什麼還要通過迭代器模式多封裝一層呢?這就是模式定義的核心所在了:讓訪問者不必關心聚合物件的內部實現(比如元素數量、KEY、具體結構等);相對來說就是讓聚合物件的內部實現不暴露給訪問者(例如避免物件被訪問者修改)。
實現我們自己的迭代器:
class RecordIterator implements Iterator{
private $position = 0;
//注意:被迭代物件屬性是私有的
private $records = array();
public function __construct(Array $records) {
$this->position = 0;
$this->records = $records;
}
function rewind() {
$this->position = 0;
}
function current() {
return $this->records[$this->position];
}
function key() {
return $this->position;
}
function next() {
++$this->position;
}
function valid() {
return isset($this->records[$this->position]);
}
}
//假如我們從MongoDB中讀取得到下列資料
$data = array(
0 => array('field' => 'value'),
1 => array('field' => 'value'),
2 => array('field' => 'value'),
3 => array('field' => 'value'),
);
//使用我們自己定義的迭代器
$records = new RecordIterator($data);
while($records->valid()){
print_r($records->current());
$records->next();
}
$records->rewind();
在GoF定義的迭代器模式中,還有兩個參與者:容器和具體容器,負責初始化並返回具體的迭代器。
//容器
interface Aggregate
{
public getIterator();
}
//具體容器
class RecordList implements Aggregate{
private $iterator;
public function __construct($data){
$this->iterator = new RecordIterator($data);
}
public function getIterator(){
return $this->iterator;
}
}
//使用
//假如我們從MongoDB中讀取得到下列資料
$data = array(
0 => array('field' => 'value'),
1 => array('field' => 'value'),
2 => array('field' => 'value'),
3 => array('field' => 'value'),
);
$recordList = new RecordList($data);
$iterator = $recordList->getIterator();
while($iterator->valid()){
print_r($iterator->current());
$iterator->next();
}
留言
張貼留言