抽象クラスを生成する抽象クラスを利用したデザインパターン。
「抽象的な工場」と訳される場合があると言われているが、言われている例をあまり見たことがない。

同じような構造のクラスを生成するパターンが複数に分岐する場合に有効。
Factory Methodパターンとの違いは正直よくわかっていないけど、Factory Methodをいっぱい作ったらAbstract Factoryなんじゃないの?ぐらいの認識。

釣り具メーカのリールロッドを生成するFactoryクラスがあり、
それぞれの、メーカはsimanoDaiwaを準備する場合。

UML

重要なところ

Abstract Factoryクラスで抽象クラスを生成するようにメソッドを定義する。
また、Abstract Factoryクラス自体も抽象クラスとして実装する。

あとは、Factoryクラスのパターンとして具象クラスを作る。
以下の例では、Daiwaファクトリクラスを作っている。

こうすることにより、Factoryクラスをパターンで分けることができる。
今回の例では、FishingTools(釣り具)のパターンがDaiwaとsimanoが存在するため、

  • Daiwaとsimanoを具象クラスとして定義
  • FishingTools(釣り具)を抽象クラスとして定義

これによりクライアントコードは抽象クラスへ依存させることができるようになる。

全体像

PHPで書いてみる

FishingTools(Abstract Factory)

1
2
3
4
5
interface FishingTools {
public function getReel() : Reel;

public function getRod() : Rod;
}

Daiwa(Concrete Factory)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
namespace FishingTools;

use Reel\Daiwa as DaiwaReel;
use Rod\Daiwa as DaiwaRod;

class Daiwa implements FishingTools
{
public function getReel() : Reel
{
return new DaiwaReel(); // 具象クラスに依存
}

public function getRod() : Rod
{
return new DaiwaRod(); // 具象クラスに依存
}
}

Client Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Fisher {

private $reel;
private $rod;

public function __construct(FishingTools $tools) // <- 抽象に依存
{
$this->reel = $tools->getReel();
$this->rod = $tools->getRod();
}

public function playFishing()
{
while($this->reel->trun()) {
// @todo: 釣れたか判定を書く
}
}
}

$fishingTools = new FishingTools\Daiwa();
$fisher = new Fisher($fishingTools);
$fisher->playFishing();

このようにClient Codeを抽象クラスに依存させることによって、
$fishingToolsはDaiwaでもsimanoでも釣り具を生成できればなんでもいい状態ができる。

この、抽象クラスに依存できるところにOOP的な旨味があるのではないかと思う。

まとめ

  1. 抽象クラス(Abstract Class)を生成する抽象クラス(Abstract Factory)を作る
  2. 実際にどの具象クラス(Concrete Class)を生成するのかは具象クラス(Concrete Factory)に実装する

所感

動機としては、会社でデザインパターンについてどれほど理解があるのかのアンケートがあった。
デザインパターンの復習と学習のため、アンケートででてきたデザインパターンを1日ずつPHPで書いてみようと思う。

39種類あったので6/24ぐらいには39種類全て書けるかと思う。

また、デザインパターンについては自信があまりないので

  • これで伝わるのか
  • そもそも認識が正しいのか

が不安

Wiki Pedia
参考