絶版されているけれど、Google booksで公開されているのが見れます。
https://books.google.co.jp/books?id=sXNh4TeQeBIC&printsec=frontcover&hl=ja#v=onepage&q&f=false
1日1パターンってことで演習してアウトプットしていきます。
iterate = 反復する、繰り返す。
Iteratorパターンはオブジェクトに対する反復操作を行うための統一APIを提供するパターン。
Iteratorパターンはオブジェクトのふるまいに注目したパターンで、利用者にリストの内部構造を隠したまま、それぞれの要素にアクセスさせるためのAPIを提供することを目的としている。
もくじ
使いどころ
- 配列が入るが、どういう配列構造かはわからない。
実装のポイント
Iteratorパターンのメリット
非カプセル化を行うパターン。
集約オブジェクトに対する操作を別クラスとして切り出して、オブジェクトが不要に肥大化したり複雑になることを避ける。切り出されたクラスを切り替えることで様々な操作をサポートできるようする。
Employees.class.php
<?php require_once 'Employee.class.php'; // SPL(Standard PHP Library) // ArrayObjectクラス // 配列をオブジェクトとして扱うためのラッパークラス // ArrayIteratorクラス // 配列用のiteratorクラス。ConcreteIteeratorクラスに相当する // FilterIteratorクラス // iterator用のフィルタクラス。また中小クラスとして定義されているため、 // 利用するにはクラスの継承を行い、acceptメソッドを実装する必要がある // IteratorAggregateクラス // Aggregateクラスに相当する。 // Iteratorを生成する為のメソッドgetIteratorが宣言されている class Employees implements IteratorAggregate { private $employees; public function __construct() { $this->employees = new ArrayObject(); } public function add(Employee $employee) { $this->employees[] = $employee; } public function getIterator() { return $this->employees->getIterator(); } }
Employees.class.php
<?php require_once 'Employee.class.php'; // SPL(Standard PHP Library) // ArrayObjectクラス // 配列をオブジェクトとして扱うためのラッパークラス // ArrayIteratorクラス // 配列用のiteratorクラス。ConcreteIteeratorクラスに相当する // FilterIteratorクラス // iterator用のフィルタクラス。また中小クラスとして定義されているため、 // 利用するにはクラスの継承を行い、acceptメソッドを実装する必要がある // IteratorAggregateクラス // Aggregateクラスに相当する。 // Iteratorを生成する為のメソッドgetIteratorが宣言されている class Employees implements IteratorAggregate { private $employees; public function __construct() { $this->employees = new ArrayObject(); } public function add(Employee $employee) { $this->employees[] = $employee; } public function getIterator() { return $this->employees->getIterator(); } }
SalesmanIterator.class.php
<?php require_once 'Employee.class.php'; // FilterIterator // オブジェクトを包み込むクラス class SalesmanIterator extends FilterIterator { public function __construct($iterator) { parent::__construct($iterator); } // ArrayIteratorオブジェクトに「動作を変更する」という機能を提供する為に、 // accetpt()メソッドに取得する条件を実装する public function accept() { $employee = $this->current(); return ( $employee->getJob() === 'SALESMAN' ); } }
iterator_client.php
<?php require_once 'Employee.class.php'; require_once 'Employees.class.php'; require_once 'SalesmanIterator.class.php'; ?> <?php function dumpWithForeach($iterator) { echo '<ul>'; foreach ($iterator as $employee) { printf('<li>%s (%d, %s)</li>', $employee->getName(), $employee->getAge(), $employee->getJob()); } echo '</ul>'; echo '<hr>'; } ?> <?php $employees = new Employees(); $employees->add( new Employee('SMITH', 32, 'CLERK') ); $employees->add( new Employee('ALLEN', 26, 'SALESMAN') ); $employees->add( new Employee('MARTIN', 50, 'SALESMAN') ); $employees->add( new Employee('KATO', 44, 'MANAGER') ); $iterator = $employees->getIterator(); /** * iteratorメソッドを利用する **/ echo '<ul>'; while ($iterator->valid()) { $empoyee = $iterator->current(); printf('<li>%s (%d, %s)</li>', $empoyee->getName(), $empoyee->getAge(), $empoyee->getJob()); $iterator->next(); } echo '</ul>'; echo '<hr>'; /** * foreachを利用する **/ dumpWithForeach($iterator); /** * 異なるiteratorで要素を取得する **/ dumpWithForeach(new SalesmanIterator($iterator));
DEMO
/demo/Design-Pattern-Primer-by-PHP/Iterator/iterator_client.php
@see