AbstractFactory パターン | デザインパターン
2022年9年23日
デザインパターン
AbstractFactory
PHP
オライリージャパンによる Head First シリーズ デザインパターン(第2版)第4章 AbstractFactory パターンを、PHPで書き直してみようという試みです。
PizzaStore.php
namespace AbstractFactory;
abstract class PizzaStore {
public function orderPizza(string $type){
$pizza = null;
$pizza = $this->createPizza($type);
$pizza->prepare();
$pizza->bake();
$pizza->cut();
$pizza->box();
return $pizza;
}
abstract public function createPizza(string $type);
}
NYPizzaStore.php
namespace AbstractFactory;
class NYPizzaStore extends PizzaStore {
public function createPizza(string $type){
$pizza = null;
$ingredientFactory = new NYPizzaIngredientFactory();
if ($type === 'チーズ') {
$pizza = new CheesePizza($ingredientFactory);
$pizza->setName('ニューヨークスタイルチーズピザ');
} else if($type === '野菜') {
$pizza = new VeggiesPizza($ingredientFactory);
$pizza->setName('ニューヨークスタイル野菜ピザ');
} else if($type === 'アサリ') {
$pizza = new ClamPizza($ingredientFactory);
$pizza->setName('ニューヨークスタイルアサリピザ');
} else if($type === 'ペパロニ') {
$pizza = new PepperoniPizza($ingredientFactory);
$pizza->setName('ニューヨークスタイルペパロニピザ');
}
return $pizza;
}
}
ChicagoPizzaStore.php
namespace AbstractFactory;
class ChicagoPizzaStore extends PizzaStore {
public function createPizza(string $type){
$pizza = null;
$ingredientFactory = new ChicagoPizzaIngredientFactory();
if ($type === 'チーズ') {
$pizza = new CheesePizza($ingredientFactory);
$pizza->setName('シカゴスタイルチーズピザ');
} else if($type === '野菜') {
$pizza = new VeggiesPizza($ingredientFactory);
$pizza->setName('シカゴスタイル野菜ピザ');
} else if($type === 'アサリ') {
$pizza = new ClamPizza($ingredientFactory);
$pizza->setName('シカゴスタイルアサリピザ');
} else if($type === 'ペパロニ') {
$pizza = new PepperoniPizza($ingredientFactory);
$pizza->setName('シカゴスタイルペパロニピザ');
}
return $pizza;
}
}
Pizza.php
namespace AbstractFactory;
abstract class Pizza {
public string $name = '';
public Dough $dough;
public Sauce $sauce;
public Cheese $cheese;
public array $veggies;
public Pepperoni $pepperoni;
public Clams $clam;
abstract function prepare() : void;
public function bake() : void {
echo '180度で25分焼く' . "\n";
}
public function cut() : void {
echo 'ピザを扇型にカットする' . "\n";
}
public function box() : void {
echo 'PizzaStoreの箱にピザを入れる' . "\n";
}
public function setName(string $name) : void {
$this->name = $name;
}
public function getName() : string {
return $this->name;
}
}
CheesePizza.php
namespace AbstractFactory;
class CheesePizza extends Pizza {
public PizzaIngredientFactory $ingredientFactory;
public function __construct(PizzaIngredientFactory $ingredientFactory) {
$this->ingredientFactory = $ingredientFactory;
}
public function prepare() : void {
echo $this->name . 'を調理' . "\n";
$this->dough = $this->ingredientFactory->createDough();
echo $this->dough->getDough() . 'をこねる' . "\n";
$this->sauce = $this->ingredientFactory->createSauce();
echo $this->sauce->getSauce() . 'を追加' . "\n";
$this->cheese = $this->ingredientFactory->createCheese();
echo $this->cheese->getCheese() . 'をトッピング' . "\n";
}
}
Soy.php
namespace AbstractFactory;
interface PizzaIngredientFactory {
public function createDough() : Dough;
public function createSauce() : Sauce;
public function createCheese() : Cheese;
public function createVehhies() : array;
public function createPepperoni() : Pepperoni;
public function createClams() : Clams;
}
NYPizzaIngredientFactory.php
namespace AbstractFactory;
class NYPizzaIngredientFactory implements PizzaIngredientFactory {
public function createDough() : Dough {
return new ThinCrustDough();
}
public function createSauce() : Sauce {
return new MarinaraSauce();
}
public function createCheese() : Cheese {
return new ReggianoCheese();
}
public function createVehhies() : array {
$veggies = [new Garlic(), new Onion(), new MushRoom(), new RedPepper()];
return $veggies;
}
public function createPepperoni() : Pepperoni {
return new SlicedPepperoni();
}
public function createClams() : Clams {
return new FreshClams();
}
}
ChicagoPizzaIngredientFactory.php
namespace AbstractFactory;
class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory {
public function createDough() : Dough {
return new ThickCrustDough();
}
public function createSauce() : Sauce {
return new PlumTomatoSauce();
}
public function createCheese() : Cheese {
return new MozzarellaCheese();
}
public function createVehhies() : array {
$veggies = [new BlackOlives(), new Spinach(), new Eggplant()];
return $veggies;
}
public function createPepperoni() : Pepperoni {
return new SlicedPepperoni();
}
public function createClams() : Clams {
return new FrozenClams();
}
}
Dough.php
namespace AbstractFactory;
interface Dough {
public function getDough() : string;
}
ThinCrustDough.php
namespace AbstractFactory;
class ThinCrustDough implements Dough {
public function getDough() : string {
return 'うすい生地';
}
}
ThickCrustDough.php
namespace AbstractFactory;
class ThickCrustDough implements Dough {
public function getDough() : string {
return '厚い生地';
}
}
Sauce.php
namespace AbstractFactory;
interface Sauce {
public function getSauce() : string;
}
MarinaraSauce.php
namespace AbstractFactory;
class MarinaraSauce implements Sauce {
public function getSauce() : string {
return 'マリナラソース';
}
}
PlumTomatoSauce.php
namespace AbstractFactory;
class PlumTomatoSauce implements Sauce {
public function getSauce() : string {
return 'プラムトマトソース';
}
}
Cheese.php
namespace AbstractFactory;
interface Cheese {
public function getCheese() : string;
}
ReggianoCheese.php
namespace AbstractFactory;
class ReggianoCheese implements Cheese {
public function getCheese() : string {
return 'すりおろしたレッジャーノチーズ';
}
}
MozzarellaCheese.php
namespace AbstractFactory;
class MozzarellaCheese implements Cheese {
public function getCheese() : string {
return 'シュレッドモッツァレラチーズ';
}
}
index.php
use AbstractFactory\NYPizzaStore;
use AbstractFactory\ChicagoPizzaStore;
$nyStore = new NYPizzaStore();
$chicagoStore = new ChicagoPizzaStore();
$pizza = $nyStore->orderPizza('チーズ');
echo 'イーサンの注文は' . $pizza->getName() . "\n\n";
$pizza = $chicagoStore->orderPizza('チーズ');
echo 'ジョエルの注文は' . $pizza->getName() . "\n\n";
出力結果
ニューヨークスタイルチーズピザを調理
うすい生地をこねる
マリナラソースを追加
すりおろしたレッジャーノチーズをトッピング
180度で25分焼く
ピザを扇型にカットする
PizzaStoreの箱にピザを入れる
イーサンの注文はニューヨークスタイルチーズピザ
シカゴスタイルチーズピザを調理
厚い生地をこねる
プラムトマトソースを追加
シュレッドモッツァレラチーズをトッピング
180度で25分焼く
ピザを扇型にカットする
PizzaStoreの箱にピザを入れる
ジョエルの注文はシカゴスタイルチーズピザ