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();
}

留言

這個網誌中的熱門文章

c語言-關於#define用法

CMD常用網管指令

PHP 與 JavaScript 之間傳值利用 json