2008-10-19 83 views
5

我試圖讓我的頭繞着SPL迭代器,我想出了兩種方法來處理它。我認爲第一個版本不那麼複雜,但第二個版本對它有構圖感(我認爲)。一個對象應該實現一個迭代器還是包含實現一個迭代器的另一個對象

我沒有看到哪一個比另一個更可取?還是我過分複雜呢?

這裏是我的想法:

對象實現一個迭代器:

class BoxOfChocolates implements Iterator { 

    private $id 
    private $name; // e.g. Valentine's Heart Box 
    private $maker; // e.g. Hersheys 
    private $items; // array 

    public function getChocolates() { 
    $query = ... 
    foreach($rows as $row) { 
     $this->_items[] = new Chocolate() ... 
    } 
    } 

    // ... necessary iterator implementation stuff 


} 

的對象包含一個迭代,能夠對象:

class BoxOfChocolates { 

    private $id; 
    private $name; 
    private $maker; 
    private $items; // chocolates object 

    public function getChocolates() { 
    $this->items = new Chocolates(); 
    $this->items->getChocolates(); 
    } 

} 


class Chocolates implements Iterator { 

    private $items; 

    public function getChocolates() { 
    $query = ... 
    foreach($rows as $row) { 
     $this->_items[] = new Chocolate() ... 
    } 
    } 

    // ... necessary iterator implementation stuff 

} 

回答

2

這要看情況而定。這盒巧克力是否包含多個集合?如果是這樣,你需要讓收藏成爲會員。

想想這樣。一箱巧克力是一個集合(即PersonList)還是一個擁有集合的東西(即一輛汽車可能擁有它的最後一個所有者的集合)。

我認爲這屬於第一組

:)

1

我建議第一組太,假定您巧克力的隱喻下是相當精確到實際的類。

一盒巧克力真的是你的巧克力的集合,因此它有意義地想要遍歷那個盒子裏的巧克力。添加單獨的巧克力列表並不真正增加任何價值,而只是似乎添加了不必要的圖層。

0

嗯,我不知道PHP,所以我不能正確回答這個問題,但我會嘗試將它與我知道的區域相關聯。

在C#中,有兩個接口:IEnumerable和IEnumerator。在你的例子中,BoxOfChocolates是Enumerable,巧克力是Enumerator。

枚舉數只有一個返回枚舉數的方法。統計員有一個當前項目的概念,並有一種移動到下一個項目的方法。在大多數情況下,Enumerator類不是「看到」的。例如,在「foreach(boxOfChoclates中的巧克力項目)」行中,「boxOfChocolates是Enumerable;枚舉器對象完全被foreach隱藏。

0

很簡單,容器是實現迭代器的地方。

0

我想你應該保持你的集合獨立於迭代器。我同意@James Curran的說法,即集合通常具有迭代器 - 事實上,它們可以有幾個。例如,你可能需要一個用堅果跳過糖果的迭代器(儘管典型的情況是需要一個逆轉排序的)。在這種情況下next()方法的含義發生變化。爲了處理這個問題,在包含自己的迭代語義的獨立類中實現迭代器。提供集合中的方法來獲取正確排序的迭代器。這確實是一個分離問題的問題。該集合不關心用戶如何迭代它,這是迭代器的關注點。

4

bbxbby,最好的解決方案通常是最簡單的一個。你絕對不會過分複雜的創建單獨的迭代器對象。事實上,PHP支持並鼓勵這種聚合提供接口。執行IteratorAggregate的對象必須包含返回IteratorgetIterator()方法。這確實是您的getChocolated()方法所做的。關於IteratorAggregate的好處是您可以直接將對象傳遞給foreach循環。您的代碼可能看起來像這樣的一個使用它的時候:

class BoxOfChocolates implements IteratorAggregate 

    private $chocolates = array(); 

    public function getIterator() { 
     return new ArrayIterator(new ArrayObject($this->chocolates))); 
    } 

} 

,然後在代碼的某個地方:

$box = new BoxOfChocolates(); 
foreach ($box as $chocolate) { ... }