アブストラクトファクトリー パターン

AbstractFactory Pattern

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の箱にピザを入れる
  ジョエルの注文はシカゴスタイルチーズピザ
      

だてめがね
...
©️ ponpocopy

とある企業で社内SEをしています。 自身の学びが誰かの為になれば、という想いで日々ブログを更新中。 PHP(CakePHP・Laravel・FuelPHP), Pyhotn(Django・Flask), C#(ASP.NET、Unity) が好きです。