Iterator Pattern
なんつうか、IteratorとかAggregateという名前がしっくりこない。Enumerable, Scannableとかのほうがしっくりくる気がする。
イテレーター(以下、スキャナーと書いてしまおう)はスキャンする対象を持っていて、そのインターフェースがhas_next, nextメソッド。集合体はスキャナーをCreateするインターフェースをもち、それがiteratorメソッド。
以下、コード;
<? /* * 集合体のインターフェース * イテレーターインターフェースを持つ */ interface Aggregate{ function iterator(); } /* * 反復動作のインターフェース * 言い換えると、集合体のスキャンに必要なインターフェース */ interface MyIterator{ function has_next(); function next(); } /* * フォトアルバム(写真の集合体) * スキャンクラスを持つ */ class PhotoAlbum implements Aggregate{ protected $photos = array(); //<--集合体はカプセル化されている protected $iterator; function __construct($args){ $this->photos = $args; } function iterator(){ return new PhotoAlbumIterator($this); } function odd_iterator(){ return new PhotoAlbumOddIterator($this); } function get_photo_at($index){ //<--ゲッター return $this->photos[$index]; } function size(){ return count($this->photos); } } /* * アルバムのイテレーター */ class PhotoAlbumIterator implements MyIterator{ protected $photo_album; //<-- 数え上げる対象(PhotoAlbum)を知っている protected $index; //<-- 数え上げる為に必要 function __construct($arg){ $this->photo_album = $arg; $this->index = 0; } function has_next(){ return $this->index < $this->photo_album->size(); } function next(){ $photo = $this->photo_album->get_photo_at($this->index); ++ $this->index; return $photo; } } class PhotoAlbumOddIterator extends PhotoAlbumIterator{ function next(){ $photo = $this->photo_album->get_photo_at($this->index); $this->index = $this->index + 2; return $photo; } } $books = array("コーヒーの写真", "コーラの写真", "ファンタの写真", "山の写真", "ダイエットコークの写真"); $photo_album = new PhotoAlbum($books); $iterator = $photo_album->iterator(); while($iterator->has_next()){ echo $iterator->next() . "<br />"; } echo "<hr />"; $odd_iterator = $photo_album->odd_iterator(); while($odd_iterator->has_next()){ echo $odd_iterator->next() . "<br />"; } ?>