Head FirstのFactoryパターンの
例え話が「ピザ屋」のお話だったので、
すんごいピザが食べたくなり、ピザホール一人で食べました。
やっぱりマルゲリータですよね。
んで、追いオリーブオイル。
Factoryパターン一族
– Simple Factory[正確にはFactoryパターンではない]
– Factory Method
– Abstract Factory
今回は最後のAbstract Factoryについてです!
Abstract Factory
オブジェクトを作成をカプセル化し、依存度を下げる。(Factory Methodと同じ)
FactoryMethodと異なり、オブジェクトコンポジションを使います。
具象クラスを指定することなく、
一連の関連オブジェクトや依存オブジェクトを作成するための
インターフェースを提供する。
→ 使い手は、抽象インターフェースを使って、
実際に作成される具体的な製品を知ることなく、
一連の製品を作成できる。
いいところ:
使い手は、具体的な製品の詳細から完全に分離されます。
→ 役割分担できて、個々のクラスの責任が小さくなる
クラス図はこんな感じ
Head Firstでは、
– 工場:ピザの食材を作る食材工場
– 製品:ピザの食材
を例としていました。
こんな感じ(PHPStormのクラス図作れるの教えてもらったので、早速)
PizzaIngredientFactoryクラスで、
関連する一連の食材(Dough, Sauce, Cheese, …)オブジェクトを
まとめてグループ化して作れるのがいいところです。
▶︎ PizzaIngredientFactory ←抽象的な食材工場
interface PizzaIngredientFactory { //実装クラスにピザの食材(製品)の作成方法は任す。 public function createDough(): DoughInterface; public function createSauce(): SauceInterface; public function createCheese(): CheeseInterface; ... }
▶︎ NYPizzaIngredientFactory (PizzaIngredientFactoryの実装クラス)
↑具象な食材工場
class NYPizzaIngredientFactory implements PizzaIngredientFactory { //具体的なピザの食材(オブジェクト)を作成する。 public function createDough(): DoughInterface { return new ThinCrustDough(); } public function createSauce(): SauceInterface { return new MarinaraSauce(); } ...
▶︎ DoughInterface ←抽象的な食材
interface DoughInterface { public function getName(): string; }
▶︎ ThinCrustDough (DoughInterfaceの実装クラス)
↑具象な食材
class ThinCrustDough implements DoughInterface { private $name; public function __construct() { $this->name = "うっすい生地"; } public function getName(): string { return $this->name; } }
ただし、食材が追加された時、
Product(MeetInterface, Bacon)の追加だけでなく、
PizzaIngredientFactoryと
PizzaIngredientFactoryを実装する全てのクラスを変更する必要があります。
→影響範囲が大きめです。
例: 肉(食材)を追加する場合
– PizzaIngredientFactory
interface PizzaIngredientFactory { //実装クラスにピザの食材(製品)の作成方法は任す。 public function createDough(): DoughInterface; public function createSauce(): SauceInterface; public function createCheese(): CheeseInterface; ... + public function createMeet(): CheeseInterface; }
– NYPizzaIngredientFactory
class NYPizzaIngredientFactory implements PizzaIngredientFactory { ... + public function createMeet() + { + //MeetInterfaceの実装クラスをインスタンス化する + return new Bacon(); + } }
ある程度、固定された一連のオブジェクトがあって、
それらを作成する必要がある時に使えそうですね。