【PHPデザインパターン】06_Iterator~順々にアクセスする
引用記事
この記事を書くきっかけになったブログです。
記事内の解説やソースコードは、こちらのブログと著者の公開リポジトリを参考にしています。
Do You PHP はてな〜[doyouphp][phpdp]PHPによるデザインパターン入門 - Iterator~順々にアクセスする
概要
- オブジェクトに対する反復操作をおこなうための統一APIを提供する。
- 具体的には、利用者にリスト(集約オブジェクト)の内部構造を隠したまま、それぞれの要素にアクセスさせるためのAPIを提供する。
- 実装することにより、異なる内部構造を持つリストの要素に同じAPIでアクセスできる。
- 「iterate」は「繰り返す」「反復する」という意味。
構成要素
Iteratorクラス
- 要素にアクセスするためのAPIを提供するクラス。
ConcreteIteratorクラス
- Iteratorクラスのサブクラス。
- リストの内部構造を把握し、それに依存する走査処理を実装する。
Aggregateクラス
- Iteratorオブジェクトを返すAPIを提供するクラス。
- クライアントの窓口に当たる。
ConcreteAggregateクラス
- Aggregateクラスのサブクラス。
- リスト固有のIteratorオブジェクトを返す。
SPLについて
SPL(Standard PHP Library)
は標準的な問題を解決するためのインターフェイスやクラスを集めたものです。
PHP5.0.0以降はデフォルトで使用できるそうです。
SPLにはイテレータが用意されており、オブジェクトを反復処理することができます。
実演
著者のソースコードとほぼ同じです。
処理の流れ
- 国名、大陸、言語の登録と出力を行う。
- SPLのイテレータを利用する。
-
Countriesクラス
はConcreteAggregateクラスに相当する。 - Countriesクラスが実装している
IteratorAggregateインターフェース
はAggregateクラスに相当する。 - Countriesクラスで生成している
ArrayObjectクラス
は、オブジェクトを配列として扱うためのクラス。そこで配列用のiteratorクラスであるArrayIteratorクラス
が利用される。 -
AsiaIteratorクラス
はConcreteIteratorクラスに相当する。大陸がAsiaの国だけを出力できるようにフィルタリングを行う。
ファイル構造
MyIterator
├── AsiaIterator.php
├── Countries.php
├── Country.php
└── my_client.php
ソースコード
my_client.php
my_client.php
<?php
namespace DoYouPhp\PhpDesignPattern\Iterator\MyIterator;
require dirname(dirname(__DIR__)).'/vendor/autoload.php';
use DoYouPhp\PhpDesignPattern\Iterator\MyIterator\Country;
use DoYouPhp\PhpDesignPattern\Iterator\MyIterator\Countries;
use DoYouPhp\PhpDesignPattern\Iterator\MyIterator\Asia;
// Countriesインスタンスを作成する
// その中に配列の要素としてCountryインスタンスをセットする
$countries = new Countries();
$countries->add(new Country('Japan', 'Asia', 'Japanese'));
$countries->add(new Country('America', 'North America', 'English'));
$countries->add(new Country('China', 'Asia', 'Chinese'));
// イテレータを取得する
$iterator = $countries->getIterator();
// フィルタリングされたイテレータを取得する
$asia_iterator = new AsiaIterator($iterator);
// foreach構文を利用して配列の要素を取り出す
function dumpWithForeach(\Iterator $iterator)
{
foreach ($iterator as $country) {
echo '国名:'.$country->getName()."\t".'大陸:'.$country->getContinent()."\t".'言語:'.$country->getLanguage().'<br>'."\n";
}
}
// Iteratorクラスのメソッドを利用して配列の要素を取り出す
// validメソッドで現在の要素が有効かチェックする
// 有効であればtrueが返り、処理が実行される
function dumpWithIterator(\Iterator $iterator)
{
while ($iterator->valid()) {
// currentメソッドで現在の要素の値を取得する
$country = $iterator->current();
echo '国名:'.$country->getName()."\t".'大陸:'.$country->getContinent()."\t".'言語:'.$country->getLanguage().'<br>'."\n";
// nextメソッドでイテレータを前方に移動する
$iterator->next();
}
}
// イテレータのメソッドを利用する
echo 'これはIteratorクラスのメソッドです'.'<br>'."\n";
dumpWithIterator($iterator);
// foreach文を利用する
echo 'これはforeach文を利用しています'.'<br>'."\n";
dumpWithForeach($iterator);
// 異なるイテレータで要素を取得する
// FilterIteratorクラスの場合、配列の取り出しはforeach構文のみ利用できる
echo 'これはAsiaIteratorクラスでフィルタリングされforeach文を利用しています'.'<br>'."\n";
dumpWithForeach($asia_iterator);
Country.php
Country.php
<?php
namespace DoYouPhp\PhpDesignPattern\Iterator\MyIterator;
// 追加する要素の各値をセットする
class Country
{
private $name;
private $continent;
private $language;
public function __construct($name, $continent, $language)
{
$this->name = $name;
$this->continent = $continent;
$this->language = $language;
}
// 各値を取得する
public function getName()
{
return $this->name;
}
public function getContinent()
{
return $this->continent;
}
public function getLanguage()
{
return $this->language;
}
}
Countries.php
Countries.php
<?php
namespace DoYouPhp\PhpDesignPattern\Iterator\MyIterator;
use DoYouPhp\PhpDesignPattern\Iterator\MyIterator\Country;
// IteratorAggregateクラスは外部イテレータを作成するためのインターフェイス
class Countries implements \IteratorAggregate
{
// Countryインスタンスが配列の要素としてセットされる
// ArrayObjectクラスのインスタンス
private $countries;
// ArrayObjectクラスはオブジェクトを配列として動作させる
public function __construct()
{
$this->countries = new \ArrayObject();
}
// 配列に新しいCountryインスタンスを追加する
public function add(Country $country)
{
$this->countries[] = $country;
}
// インターフェイスのメソッド
// イテレータを取得して返す
// 戻り値はIteratorクラスのオブジェクト
public function getIterator()
{
return $this->countries->getIterator();
}
}
AsiaIterator.php
AsiaIterator.php
<?php
namespace DoYouPhp\PhpDesignPattern\Iterator\MyIterator;
use DoYouPhp\PhpDesignPattern\Iterator\MyIterator\Country;
// FilterIteratorクラスはフィルタリングを行う抽象クラス
class AsiaIterator extends \FilterIterator
{
// コンストラクタ
public function __construct($iterator)
{
parent::__construct($iterator);
}
// FilterIteratorクラスの抽象メソッド
// 配列の要素数だけ繰り返し実行される
public function accept()
{
// getInnerIteratorメソッドで内部イテレータを取得する
// currentメソッドで現在の要素の値を取得する
// 両方ともFilterIteratorクラスのメソッド
$country = $this->getInnerIterator()->current();
// continentがAsiaの要素のみ抽出する
return ($country->getContinent() === 'Asia');
}
}
Author And Source
この問題について(【PHPデザインパターン】06_Iterator~順々にアクセスする), 我々は、より多くの情報をここで見つけました https://qiita.com/yukibe/items/7fe363f82e17cf59f51d著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .