Iterator パターン | デザインパターン
2022年9年24日
デザインパターン
Iterator
PHP
オライリージャパンによる Head First シリーズ デザインパターン(第2版)第9章 Iterator パターンを、PHPで書き直してみようという試みです。
MenuItem.php
namespace Iterator; class MenuItem { public string $name; public string $description; public bool $vegetarian; public float $price; public function __construct(string $name, string $description, bool $vegetarian, float $price) { $this->name = $name; $this->description = $description; $this->vegetarian = $vegetarian; $this->price = $price; } public function getName() : string { return $this->name; } public function getDescription() : string { return $this->description; } public function getPrice() : float { return $this->price; } public function isVegetarian() : bool { return $this->vegetarian; } }
Menu.php
namespace Iterator; interface Menu { public function createIterator(); }
PancakeHouseMenu.php
namespace Iterator; class PancakeHouseMenu implements Menu { public array $menuItems; public function __construct() { self::addItem('K&Bのパンケーキ朝食', 'スクランブルエッグとトースト付きパンケーキ', true, 2.99); self::addItem('いつものパンケーキ朝食', '卵焼きとソーセージ付きパンケーキ', false, 2.99); self::addItem('ブルーベリーパンケーキ', '新鮮なブルーベリーを使ったパンケーキ', true, 3.49); self::addItem('ワッフル', 'ブルーベリーかいちごの好きな方を乗せたワッフル', true, 3.59); } public function addItem(string $name, string $description, bool $vegetarian, float $price) : void { $menuItem = new MenuItem($name, $description, $vegetarian, $price); $this->menuItems[] = $menuItem; } public function createIterator() { return new PancakeHouseMenuIterator($this->menuItems); } }
DinerMenu.php
namespace Iterator; class DinerMenu implements Menu { public int $MAX_ITEMS = 6; public int $numberOfItems = 0; public array $menuItems; public function __construct() { self::addItem('ベジタリアンBTL', 'レタス、トマト、(フェイク)ベーコンを挟んだ小麦パンサンドイッチ', true, 2.99); self::addItem('BLT', 'レタス、トマト、ベーコンを挟んだ小麦パンサンドイッチ', false, 2.99); self::addItem('本日のスープ', 'ポテトサラダを添えた本日のスープ', false, 3.29); self::addItem('ホットドッグ', 'ザワークラウト、レリッシュ、玉ねぎ、チーズを挟んだホットドッグ', false, 3.05); self::addItem('蒸し野菜と玄米', '玄米の上に蒸し野菜', true, 3.99); self::addItem('パスタ', 'マリナラソーススパゲッティとサワードウパン', true, 3.89); } public function addItem(string $name, string $description, bool $vegetarian, float $price) : void { if ($this->numberOfItems >= $this->MAX_ITEMS) { echo 'すみません、メニューはいっぱいです!メニューに項目を追加できません。'; } else { $menuItem = new MenuItem($name, $description, $vegetarian, $price); $this->menuItems[$this->numberOfItems] = $menuItem; $this->numberOfItems = $this->numberOfItems + 1; } } public function createIterator() { return new DinerMenuIterator($this->menuItems); } }
CafeMenu.php
namespace Iterator; class CafeMenu implements Menu { public array $menuItems; public function __construct() { self::addItem('野菜バーガーとフライドポテト', '小麦パンにレタスとトマトを挟んだ野菜バーガーとフライドポテト', true, 3.99); self::addItem('本日のスープ', 'サラダがついた本日のスープ', false, 2.99); self::addItem('ブリトー', 'インゲン豆、サルサ、グアカモーレ入りの大きなブリトー', true, 4.29); } public function addItem(string $name, string $description, bool $vegetarian, float $price) : void { $menuItem = new MenuItem($name, $description, $vegetarian, $price); $this->menuItems[] = $menuItem; } public function createIterator() { return new PancakeHouseMenuIterator($this->menuItems); } }
Iterator.php
namespace Iterator; interface Iterator { public function hasNext() : bool; public function next() : MenuItem; }
PancakeHouseMenuIterator.php
namespace Iterator; class PancakeHouseMenuIterator implements Iterator { public int $position = 0; public array $items; public function __construct(array $items) { $this->items = $items; } public function next() : MenuItem { $menuItem = $this->items[$this->position++]; return $menuItem; } public function hasNext() : bool { if ($this->position >= count($this->items)) { return false; } else { return true; } } }
DinerMenuIterator.php
namespace Iterator; class DinerMenuIterator implements Iterator { public int $position = 0; public array $items; public function __construct(array $items) { $this->items = $items; } public function next() : MenuItem { $menuItem = $this->items[$this->position++]; return $menuItem; } public function hasNext() : bool { if ($this->position >= count($this->items)) { return false; } else { return true; } } }
CafeMenuIterator.php
namespace Iterator; class CafeMenuIterator implements Iterator { public int $position = 0; public array $items; public function __construct(array $items) { $this->items = $items; } public function next() : MenuItem { $menuItem = $this->items[$this->position++]; return $menuItem; } public function hasNext() : bool { if ($this->position >= count($this->items)) { return false; } else { return true; } } }
Waitress.php
namespace Iterator; class Waitress { public array $menus; public function __construct(array $menus) { $this->menus = $menus; } public function printMenu() : void { foreach($this->menus as $menus) { $menu = $menus->createIterator(); self::_printMenu($menu); } } private function _printMenu($iterator) : void { while ($iterator->hasNext()) { $menuItem = $iterator->next(); echo $menuItem->getName() . '、'; echo $menuItem->getPrice() . ' -- '; echo $menuItem->getDescription(); echo "\n"; } } }
index.php
use Iterator\PancakeHouseMenu; use Iterator\DinerMenu; use Iterator\CafeMenu; use Iterator\Waitress; $pancakeHouseMenu = new PancakeHouseMenu(); $dinerMenu = new DinerMenu(); $cafeMenu = new CafeMenu(); $waitress = new Waitress([$pancakeHouseMenu, $dinerMenu, $cafeMenu]); $waitress->printMenu();
出力結果
K&Bのパンケーキ朝食、2.99 -- スクランブルエッグとトースト付きパンケーキ いつものパンケーキ朝食、2.99 -- 卵焼きとソーセージ付きパンケーキ ブルーベリーパンケーキ、3.49 -- 新鮮なブルーベリーを使ったパンケーキ ワッフル、3.59 -- ブルーベリーかいちごの好きな方を乗せたワッフル ベジタリアンBTL、2.99 -- レタス、トマト、(フェイク)ベーコンを挟んだ小麦パンサンドイッチ BLT、2.99 -- レタス、トマト、ベーコンを挟んだ小麦パンサンドイッチ 本日のスープ、3.29 -- ポテトサラダを添えた本日のスープ ホットドッグ、3.05 -- ザワークラウト、レリッシュ、玉ねぎ、チーズを挟んだホットドッグ 蒸し野菜と玄米、3.99 -- 玄米の上に蒸し野菜 パスタ、3.89 -- マリナラソーススパゲッティとサワードウパン 野菜バーガーとフライドポテト、3.99 -- 小麦パンにレタスとトマトを挟んだ野菜バーガーとフライドポテト 本日のスープ、2.99 -- サラダがついた本日のスープ ブリトー、4.29 -- インゲン豆、サルサ、グアカモーレ入りの大きなブリトー