Composite パターン | デザインパターン
2022年9年24日
デザインパターン
Composite
PHP
オライリージャパンによる Head First シリーズ デザインパターン(第2版)第9章 Composite パターンを、PHPで書き直してみようという試みです。
MenuItem.php
namespace Composite;
class MenuItem extends MenuComponent {
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;
}
public function print() : void {
echo self::getName();
echo (self::isVegetarian() ? '(v)' : null);
echo '、' . self::getPrice() . "\n";
echo ' -- ' . self::getDescription() . "\n";
}
}
Menu.php
namespace Composite;
class Menu extends MenuComponent {
public array $menuComponents = [];
public string $name;
public string $description;
public function __construct(string $name, string $description) {
$this->name = $name;
$this->description = $description;
}
public function add(MenuComponent $menuComponent) : void {
$this->menuComponents[] = $menuComponent;
}
public function remove(int $i) : void {
unset($this->menuComponents[$i]);
}
public function getChild(int $i) : MenuComponent {
return $this->menuComponents[$i];
}
public function getName() : string {
return $this->name;
}
public function getDescription() : string {
return $this->description;
}
public function print() : void {
echo "\n" . self::getName();
echo '、' . self::getDescription() . "\n";
echo '-------------------------' . "\n";
foreach($this->menuComponents as $menuComponent) {
$menuComponent->print();
}
}
MenuComponent.php
namespace Composite;
abstract class MenuComponent {
public function add(MenuComponent $menuComponent) : void {
throw new Exception('UnsupportedOperationException',500);
}
public function remove(int $i) : void {
throw new Exception('UnsupportedOperationException',500);
}
public function getChild(int $i) : MenuComponent {
throw new Exception('UnsupportedOperationException',500);
}
public function getName() : string {
throw new Exception('UnsupportedOperationException',500);
}
public function getDescription() : string {
throw new Exception('UnsupportedOperationException',500);
}
public function getPrice() : float {
throw new Exception('UnsupportedOperationException',500);
}
public function isVegetarian() : bool {
throw new Exception('UnsupportedOperationException',500);
}
public function print() : void {
throw new Exception('UnsupportedOperationException',500);
}
}
Waitress.php
namespace Composite;
class Waitress {
public MenuComponent $allMenus;
public function __construct(MenuComponent $allMenus) {
$this->allMenus = $allMenus;
}
public function printMenu() : void {
$this->allMenus->print();
}
}
index.php
出力結果
すべてのメニュー、全てを統合したメニュー ------------------------- パンケーキハウスメニュー、朝食 ------------------------- K&Bのパンケーキ朝食(v)、2.99 -- スクランブルエッグとトースト付きパンケーキ いつものパンケーキ朝食、2.99 -- 卵焼きとソーセージ付きパンケーキ ブルーベリーパンケーキ(v)、3.49 -- 新鮮なブルーベリーを使ったパンケーキ ワッフル(v)、3.59 -- ブルーベリーかいちごの好きな方を乗せたワッフル 食堂メニュー、昼食 ------------------------- ベジタリアンBTL(v)、2.99 -- レタス、トマト、(フェイク)ベーコンを挟んだ小麦パンサンドイッチ BLT、2.99 -- レタス、トマト、ベーコンを挟んだ小麦パンサンドイッチ 本日のスープ、3.29 -- ポテトサラダを添えた本日のスープ Hot Dog、3.05 -- ザワークラウト、レリッシュ、玉ねぎ、チーズを挟んだホットドッグ パスタ(v)、3.89 -- マリナラソーススパゲッティとサワードウパン デザートメニュー、もちろんデザート! ------------------------- アップルパイ(v)、1.59 -- バニラアイスクリームをのせたフレーク上生地のアップルパイ チーズケーキ(v)、1.99 -- チョコレートグラハム生地のクリーミーなニューヨークチーズケーキ シャーベット(v)、1.89 -- ラズベリーシャーベットとライムシャーベット カフェメニュー、夕食 ------------------------- 野菜バーガーとフライドポテト(v)、3.99 -- 小麦パンにレタスとトマトを挟んだ野菜バーガーとフライドポテト 本日のスープ、2.99 -- サラダがついた本日のスープ ブリトー(v)、4.29 -- インゲン豆、サルサ、グアカモーレ入りの大きなブリトー