PHP設計模式漫談之迭代器模式
原創(chuàng)【51CTO獨家特稿】今天《PHP設計模式漫談》系列的主角是迭代器(Iterator)模式,它在一個很常見的過程上提供了一個抽象:位于對象圖不明部分的一組對象(或標量)集合上的迭代。迭代有幾種不同的具體執(zhí)行方法:在數(shù)組屬性,集合對象,數(shù)組,甚至一個查詢結果集之上迭代。
在對象的世界里,迭代器模式要維持類似數(shù)組的功能,看作是一個非侵入性對象刻面(facet),Client類往往分離自真實對象實現(xiàn),指iterator接口。只要有可能,我們可以給迭代器傳送一個引用,代替將來可能發(fā)生變化的具體或抽象類。
參與者:
◆客戶端(Client):引用迭代器模式的方法在一組值或對象上執(zhí)行一個循環(huán)。
◆迭代器(Iterator):在迭代過程上的抽象,包括next(),isFinished(),current()等方法。
◆具體迭代器(ConcreteIterators):在一個特定的對象集,如數(shù)組,樹,組合,集合等上實現(xiàn)迭代。
通過Traversable接口,PHP原生態(tài)支持迭代器模式,這個接口由Iterator和IteratorAggregate做了擴展,這兩個子接口不僅是定義了一套標準的方法,每個Traversable對象都可以原封不動地傳遞給foreach(),foreach是迭代器的主要客戶端,Iterator實現(xiàn)是真正的迭代器,而IteratorAggregate是有其它職責的Traversable對象,它通過getIterator()方法返回一個Iterator。
標準PHP庫是PHP中綁定的唯一通用目的面向對象庫,定義了額外的接口和公用類。OuterIterator實現(xiàn)裝飾一個Iterator,CachingIterator和LimitIterator是這個接口的兩個例子。
RecursiveIterator是Iterator接口為樹形結構實現(xiàn)的一個擴展,它定義了一組額外的方法檢查迭代中當前元素的子對象是否存在。RecursiveArrayIterator和RecursiveDirectoryIterator是這個接口的實現(xiàn)示例,這些類型的迭代器可以原樣使用,或是用一個RecursiveIteratorIterator橋接到一個普通的迭代器契約。這個OuterIterator實現(xiàn)將會根據(jù)構造參數(shù)執(zhí)行深度優(yōu)先或廣度優(yōu)先遍歷。
使用RecursiveIteratorIterator時,可以將其傳遞給foreach,請看后面的代碼示例,了解RecursiveIterators的不同用法和它們的超集Iterator。最后,SeekableIterators向契約添加了一個seek()方法,它可以用于移動Iterator的內(nèi)部狀態(tài)到一個特定的迭代點。#p#
注意,迭代器是比對象集更好的抽象,因為我們可以讓InfiniteIterators,NoRewindIterators等,不用與普通數(shù)組陣列與一致,因此,Iterator缺少count()函數(shù)等功能。
在PHP官方手冊中可以找到完整的SPL迭代器列表。得益于對PHP的強力支持,使用迭代器模式的大部分工作都包括在標準實現(xiàn)中,下面的代碼示例就利用了標準Iterator和RecursiveIterators的功能。
- <?php
- /**
- * Collection that wraps a numeric array.
- * All five public methods are needed to implement
- * the Iterator interface.
- */
- class Collection implements Iterator
- {
- private $_content;
- private $_index = 0;
- public function __construct(array $content)
- {
- $this->_content = $content;
- }
- public function rewind()
- {
- $this->_index = 0;
- }
- public function valid()
- {
- return isset($this->_content[$this->_index]);
- }
- public function current()
- {
- return $this->_content[$this->_index];
- }
- public function key()
- {
- return $this->_index;
- }
- public function next()
- {
- $this->_index++;
- }
- }
- $arrayarray = array('A', 'B', 'C', 'D');
- echo "Collection: ";
- foreach (new Collection($array) as $key => $value) {
- echo "$key => $value. ";
- }
- echo "\n";
- /**
- * Usually IteratorAggregate is the interface to implement.
- * It has only one method, which must return an Iterator
- * already defined as another class (e.g. ArrayIterator)
- * Iterator gives a finer control over the algorithm,
- * because all the hook points of Iterator' contract
- * are available for implementation.
- */
- class NumbersSet implements IteratorAggregate
- {
- private $_content;
- public function __construct(array $content)
- {
- $this->_content = $content;
- }
- public function contains($number)
- {
- return in_array($number, $this->_content);
- }
- /**
- * Only this method is necessary to implement IteratorAggregate.
- * @return Iterator
- */
- public function getIterator()
- {
- return new ArrayIterator($this->_content);
- }
- }
- echo "NumbersSet: ";
- foreach (new NumbersSet($array) as $key => $value) {
- echo "$key => $value. ";
- }
- echo "\n";
- // let's play with RecursiveIterator implementations
- $it = new RecursiveArrayIterator(array(
- 'A',
- 'B',
- array(
- 'C',
- 'D'
- ),
- array(
- array(
- 'E',
- 'F'
- ),
- array(
- 'G',
- 'H',
- 'I'
- )
- )
- ));
- // $it is a RecursiveIterator but also an Iterator,
- // so it loops normally over the four elements
- // of the array.
- echo "Foreach over a RecursiveIterator: ";
- foreach ($it as $value) {
- echo $value;
- // but RecursiveIterators specify additional
- // methods to explore children nodes
- $children = $it->hasChildren() ? '{Yes}' : '{No}';
- echo $children, ' ';
- }
- echo "\n";
- // we can bridge it to a different contract via
- // a RecursiveIteratorIterator, whose cryptic name
- // should be read as 'an Iterator that spans over
- // a RecursiveIterator'.
- echo "Foreach over a RecursiveIteratorIterator: ";
- foreach (new RecursiveIteratorIterator($it) as $value) {
- echo $value;
- }
- echo "\n";
原文名:Practical Php Patterns: Iterator 作者:Giorgio
原文出處:http://giorgiosironi.blogspot.com/search/label/practical%20php%20patterns
【PHP設計模式系列】