SimpleFactoryを使ってピザショップを実装する
はじめに
SimpleFactoryはデザインパターンのFactoryパターンの簡易版です。
Factoryは工場という意味で、その名の通り「クラスのインスタンス化を担ってくれるオブジェクト」がFactoryです。
条件分岐で各クラスをインスタンス化しているような実装に適用すると、保守性を向上することができます!
環境
- Laravel 9.38.0
- PHP 8.1.12
Laravel Sailで環境構築しています。
https://readouble.com/laravel/9.x/ja/sail.html
参考
今回の実装について
- ピザショップを想定
- ピザの種類は複数あり、今後増減が想定される
SimpleFactory適用前
はじめに、SimpleFactory適用前の実装です。
次のようなコードでピザショップを実現できます。
class PizzaStore
{
public function orderPizza(string $type): Pizza
{
$pizza = null;
// 将来的にピザの種類が変更される可能性が高い
// 変更に対して閉じていない→カプセル化すべき
switch ($type) {
case 'チーズ':
$pizza = new CheesePizza();
break;
case 'アサリ':
$pizza = new ClamPizza();
break;
case 'ペパロニ':
$pizza = new PepperoniPizza();
break;
}
// 変更されない箇所
$pizza->prepare();
$pizza->bake();
$pizza->cut();
$pizza->box();
return $pizza;
}
}
PizzaStoreクラスにorderPizzaメソッドを実装しました。
ピザの種類を引数として受け取り、switch文で分岐してそれぞれのピザを作成しています。
上記の実装の場合、条件分岐が他の部分にも分散していることが予想されますし、ピザの種類の増減があった際に分散している箇所全てを修正しなければいけないという問題があります。
このような問題を解決するために、変更される可能性が高い部分と変更されない部分を分けてカプセル化する方法がSimpleFactoryになります。
したがって、各ピザインスタンスを生成する部分は変更される可能性が高いため、SimplePizzaFactoryクラスを作成し分離してみましょう!
SimpleFactory適用後
クラス図は以下のようになります。
①SimplePizzaFactory
各ピザインスタンスの生成をのみを扱うクラスとして、SimplePizzaFactoryクラスを実装します。
class SimplePizzaFactory
{
/**
* ピザの作成
*
* @param string $type
* @return Pizza
*/
public function createPizza(string $type): Pizza
{
$pizza = null;
switch ($type) {
case 'チーズ':
$pizza = new CheesePizza();
break;
case 'アサリ':
$pizza = new ClamPizza();
break;
case 'ペパロニ':
$pizza = new PepperoniPizza();
break;
}
return $pizza;
}
}
②PizzaStore
SimplePizzaFactoryのクライアントとして、PizzaStoreクラスを実装します。
class PizzaStore
{
/**
* ピザを作成するFactory
*
* @var SimplePizzaFactory
*/
private SimplePizzaFactory $factory;
/**
* コンストラクタ
*
* @param SimplePizzaFactory $factory
*/
public function __construct(SimplePizzaFactory $factory)
{
$this->factory = $factory;
}
/**
* ピザの注文
*
* @param string $type
* @return Pizza
*/
public function orderPizza(string $type): Pizza
{
$pizza = $this->factory->createPizza($type);
$pizza->prepare();
$pizza->bake();
$pizza->cut();
$pizza->box();
return $pizza;
}
}
createPizzaメソッドを作成することで、条件分岐を一つにまとめることができるようになりました!
さらに、PizzaStoreクラスはピザの種類が何かについて知る必要がなくなったことで、ピザの種類に変更があった際の影響が少なくなっています!
さいごに
今回はFactoryパターンの簡易版のSimpleFactoryについてでした。
少しでもお役に立てれば幸いです。
最後までお読みいただきありがとうございました。
Discussion