您好,登錄后才能下訂單哦!
PHP中怎么實現迭代器模式,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
迭代器有時又稱光標(cursor)是程式設計的軟件設計模式,可在容器物件(container,例如list或vector)上遍訪的接口,設計人員無需關心容器物件的內容,現在呢,各種語言實作Iterator的方式皆不盡同,有些面向對象語言像Java, C#, Python, Delphi都已將Iterator的特性內建語言當中,完美的跟語言整合,我們稱之隱式迭代器(implicit iterator),但像是C++語言本身就沒有Iterator的特色,但STL仍利用template實作了功能強大的iterator。
但是,PHP5開始支持了接口, 并且內置了Iterator接口, 所以如果你定義了一個類,并實現了Iterator接口,那么你的這個類對象就是ZEND_ITER_OBJECT,否則就是ZEND_ITER_PLAIN_OBJECT。對于ZEND_ITER_PLAIN_OBJECT的類,foreach會通過HASH_OF獲取該對象的默認屬性數組,然后對該數組進行foreach,而對于ZEND_ITER_OBJECT的類對象,則會通過調用對象實現的Iterator接口相關函數來進行foreach。
咱們什么也別說,先來看下迭代器的定義,那就是提供一種方法順序訪問一個聚合對象中各個元素,而又不暴露該對象的內部顯示。它可幫助構造特定的對象,那些對象能夠提供單一標準接口循環或迭代任何類型的可計數數據。來看下迭代器模式的結構圖:
咋樣,反正我現在是一頭霧水。。。
再來看下迭代器需要用到的內部方法:
Iterator::current — Return the current element 返回當前元素
Iterator::key — Return the key of the current element 返回當前元素的鍵
Iterator::next — Move forward to next element 移向下一個元素
Iterator::rewind — Rewind the Iterator to the first element 重新回到第一個元素
Iterator::valid — Checks if current position is valid 檢查當前位置的有效性
咱不廢話哈,直接來看下網上比較經典的一個實例:
class MyIterator implements Iterator { private $var = array(); public function __construct($array) { if (is_array($array)) { $this->var = $array; } } public function rewind() { echo "倒回第一個元素\n"; reset($this->var); } public function current() { $var = current($this->var); echo "當前元素: $var\n"; return $var; } public function key() { $var = key($this->var); echo "當前元素的鍵: $var\n"; return $var; } public function next() { $var = next($this->var); echo "移向下一個元素: $var\n"; return $var; } public function valid() { $var = $this->current() !== false; echo "檢查有效性: {$var}\n"; return $var; } } $values = array(1,2,3); $it = new MyIterator($values); foreach ($it as $k => $v) { print "此時鍵值對 -- key $k: value $v\n\n"; }
運行之后的結果如下:
我們可以想一下,如果把集合對象和對集合對象的操作放在一起,當我們想換一種方式遍歷集合對象中元素時,就需要修改集合對象了,違背“單一職責原則”,而迭代器模式將數據結構和數據結構的算法分離開,兩者可獨立發展。
來看下迭代器的優點:
1.支持多種遍歷方式。比如有序列表,我們根據需要提供正序遍歷、倒序遍歷兩種迭代器。用戶只需要得到我們的迭代器,就可以對集合執行遍歷操作
2.簡化了聚合類。由于引入了迭代器,原有的集合對象不需要自行遍歷集合元素了
3.增加新的聚合類和迭代器類很方便,兩個維度上可各自獨立變化
4.為不同的集合結構提供一個統一的接口,從而支持同樣的算法在不同的集合結構上操作
缺點就是迭代器模式將存儲數據和遍歷數據的職責分離增加新的集合對象時需要增加對應的迭代器類,類的個數成對增加,在一定程度上增加系統復雜度。
它的使用場景,我們可以參考如下幾點:
1.訪問一個聚合對象內容而無須暴露它的內部顯示
2.需要為聚合對象提供多種遍歷方式
3.為遍歷不同的聚合結構提供一個統一的接口
我們要知道,最基本的迭代器接口是Iterator,來看下Iterator里面規范的方法:
Iterator extends Traversable { /* 方法 */ 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 )//檢查當前位置是否有效 }
完事,我們如果要進行遍歷的類必須實現Iterator里面的抽象方法,如下:
class Season implements Iterator{ private $position = 0;//指針指向0 private $arr = array('春','夏','秋','冬'); public function rewind(){ return $this -> position = 0; } public function current(){ return $this -> arr[$this -> position]; } public function key(){ return $this -> position; } public function next() { ++$this -> position; } public function valid() { return isset($this -> arr[$this -> position]); } } $obj = new Season; foreach ($obj as $key => $value) { echo $key.':'.$value."\n"; }
最后,咱們來看一個網上找的用迭代器模式來實現的一個斐波那契數列。
我們都知道,斐波那契數列通常做法是用遞歸實現,當然還有其它的方法,咱們這里用PHP的迭代器來實現一個斐波納契數列,幾乎沒有什么難度,只是把類里的next()方法重寫了一次。注釋已經寫到代碼中,也是相當好理解的,如下:
class Fibonacci implements Iterator { private $previous = 1; private $current = 0; private $key = 0; public function current() { return $this->current; } public function key() { return $this->key; } public function next() { // 關鍵在這里 // 將當前值保存到 $newprevious $newprevious = $this->current; // 將上一個值與當前值的和賦給當前值 $this->current += $this->previous; // 前一個當前值賦給上一個值 $this->previous = $newprevious; $this->key++; } public function rewind() { $this->previous = 1; $this->current = 0; $this->key = 0; } public function valid() { return true; } } $seq = new Fibonacci; $i = 0; foreach ($seq as $f) { echo "$f "; if ($i++ === 15) break; }
輸出的結果如下:
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。