※学習用メモ デザインパターン:Factory Method編[PHP]

# Factory Methodパターンとはどういうものか

Factoryとは**工場**という意味です。

>Factory Method パターンは、他のクラスのコンストラクタをサブクラスで上書き可能な自分のメソッドに置き換えることで、 アプリケーションに特化したオブジェクトの生成をサブクラスに追い出し、クラスの再利用性を高めることを目的とする。(wikipediaより)

ポイントを要約すると、**親クラスであるファクトリが、実際のオブジェクトの生成をサブクラスに委譲する**ということです。

## 登場するクラス
・抽象クラス
　Productクラス:生成物の抽象クラス
　Creatorクラス:Factoryクラス
・具象クラス
　ConcreteProductクラス:生成物の具象クラス
　ConcreteCreatorクラス:オブジェクト生成の具体的の実装が記述されたサブクラス

[参考]
https://ja.wikipedia.org/wiki/Factory_Method_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3
https://qiita.com/shoheiyokoyama/items/d752834a6a2e208b90ca
https://www.techscore.com/tech/DesignPattern/FactoryMethod.html/
https://think-on-object.blogspot.com/2011/11/factoryfactory-methodabstract-factory.html

# Factory Methodパターンを用いるメリット/デメリット

・メリット
個々のインスタンス生成の実処理をサブクラス内で行うため、生成処理全体を小分けにし、簡潔な状態にすることができる。

・デメリット
インスタンスを変更する場合、Factoryクラスを変更する必要がある

# サンプルコード

## 仕様

・AppleかAndroidかを判断する

生成物の抽象クラス(Product)
このクラスでは生成物のインターフェースを記述します。

```Maker.class.php
abstract class Maker
{
    protected $name = "";
    protected $brouser = "";
    
    public function getName()
    {
        return $this->name;
    }
    
    public function getBrouser()
    {
        return $this->brouser;
    }
    
    public function getInformation()
    {
        return "Maker:" . $this->getName() . "\n" . "BrouserName:" . $this->getBrouser() . "\n";
    }
}
```

Factoryクラス(Creator)
このクラスでオブジェクトを生成する流れを実装します。
今回は抽象メソッドにしていますが、createSmartphoneメソッドにデフォルトの処理を入れても良いです。

```SmartphoneFactory.class.php
abstract class SmartphoneFactory
{
    public function create()
    {
        $smartphone = $this->createSmartphone();
        return $smartphone;
    }
    
    abstract protected function createSmartphone(); // デフォルト処理を設定したい場合はここに入れればよい
}
```

生成物の具象クラス(ConcreteProduct)
実際に生成するオブジェクトの設定を行います。

```Apple.class.php
class Apple extends Maker
{
    protected $name = "Apple";
    protected $brouser = "Safari";
}
```

```Google.class.php
class Google extends Maker
{
    protected $name = "Android";
    protected $brouser = "GoogleChrome";
}
```

Factory Methodを含むサブクラス(ConcreteCreator)
このクラスで先のFactoryクラスのcreateSmartphoneメソッドをオーバーライドし、それぞれで異なるインスタンスを生成している。
この場合それぞれオーバーライドしたcreateSmartphoneメソッドが**Factory Method**である。

```AppleSmartphoneFactory.class.php
class AppleSmartphoneFactory extends SmartphoneFactory
{
    // Factory Method
    protected function createSmartphone()
    {
        return new Apple();
    }
}
```

```AndroidSmartphoneFactory.class.php
class AndroidSmartphoneFactory extends SmartphoneFactory
{
    // Factory Method
    protected function createSmartphone()
    {
        return new Google();
    }
}
```

## 使ってみる

```php
$appleSmartPhoneFactory = new AppleSmartphoneFactory();
$appleSmartPhone = $appleSmartPhoneFactory->create();

$androidSmartphoneFactory = new AndroidSmartphoneFactory();
$androidSmartphone = $androidSmartphoneFactory->create();

echo $appleSmartPhone->getInformation();
echo $androidSmartphone->getInformation();

/*結果
Maker:Apple
BrouserName:Safari
Maker:Android
BrouserName:GoogleChrome
*/
```

# まとめ

・Factory Methodパターンは、異なるインスタンスを作成する機構を使用したい場合、専用のサブクラスを用意することでオブジェクトの生成部分のみ変更する形となっている。
・オブジェクトの生成自体を動的に処理する形(Factoryパターン)が多く使用される印象であるが、ここでは一旦Factory Methodなのでメソッドのみに注目しました。