インターフェイスだけを使って、抽象的な部品で抽象的な製品を作成する。
これをAbstract Factoryパターンという
以下のようなファイル構成になっている。
<?php abstract class Item { protected $caption; public function __construct($caption) { $this->caption = $caption; } public abstract function makeHTML(); }
LinkとTrayのスーパークラスになっている。
captionフィールドはこの項目の「見出し」を表す。
<?php require_once("Item.class.php"); abstract class Link extends Item { protected $url; public function __construct($caption, $url) { parent::__construct($caption); $this->url = $url; } }
HTMLのハイパーリンクを抽象的に表現したクラス。
なお、スーパークラスの抽象メソッドは実装していない。
<?php require_once("Item.class.php"); abstract class Tray extends Item { protected $tray; public function __construct($caption) { parent::__construct($caption); $this->tray = array(); } public function add($item) { $this->tray[] = $item; } }
複数のTrayやLinkを集めて一まとめにするクラス。
addメソッドを使って集める。
スーパークラスの抽象メソッドは実装していない。
<?php abstract class Page { protected $title; protected $author; protected $content; public function __construct($title, $author) { $this->title = $title; $this->author = $author; $this->content = array(); } public function add($item) { $this->content[] = $item; } public function output() { try { $filename = $this->title."html"; $this->makeHTML(); echo $filename."を作成しました。"; } catch (Exception $e) { echo $e; exit; } } public abstract function makeHTML(); }
HTML全体を抽象的に表現したクラス。
outputメソッドでタイトルを元にファイル名を決定し、
makeHTMLメソッドを使って自分自身のHTMLの内容を書き込んでいる。
<?php require_once("listfactory/ListFactory.class.php"); abstract class Factory { public static function getFactory($classname) { $factory = null; try { $factory = new $classname; } catch (Exception $e) { echo $e; exit; } return $factory; } public abstract function createLink($caption, $url); public abstract function createTray($caption); public abstract function createPage($title, $author); }
作成する具体的な工場のクラス名を引数にして、そのクラスのインスタンスを作る。
定義された抽象メソッドは、この抽象的な工場で部品や製品を作成するときに用いるもいの。
実際の具体的な作成はサブクラスに任せている。
<?php require_once("factory/Factory.class.php"); class Main { public function __construct($classname) { $factory = Factory::getFactory($classname); $asahi = $factory->createLink("朝日新聞", "http://www.asahi.com/"); $yomiuri = $factory->createLink("読売新聞", "http://www.yomiuri.co.jp/"); $yahoo = $factory->createLink("Yahoo!", "http://www.yahoo.co.jp/"); $google = $factory->createLink("Google", "http://www.yahoo.co.jp/"); $trynews = $factory->createTray("新聞"); $trynews->add($asahi); $trynews->add($yomiuri); $trysearch = $factory->createTray("サーチエンジン"); $trysearch->add($yahoo); $trysearch->add($google); $page = $factory->createPage("LinkPage", "當銘大河"); $page->add($trynews); $page->add($trysearch); $page->output(); } } new Main("ListFactory");
実行クラス。
ここでは抽象クラスのFactoryがあるだけで、
具体的な部品、製品、工場が一切出てきていない。
<?php require_once("listfactory/ListLink.class.php"); require_once("listfactory/ListTray.class.php"); require_once("listfactory/ListPage.class.php"); class ListFactory extends Factory { public function createLink($caption, $url) { return new ListLink($caption, $url); } public function createTray($caption) { return new ListTray($caption); } public function createPage($title, $author) { return new ListPage($title, $author); } }
AbstructFactory?役によって作り出される抽象的な部分や製品のインターフェイスを定める。
サンプルプログラムではLinkクラス、Trayクラス、Pageクラスがこの役をつためる
AbstructProduct?役のインスタンスを作り出すためのインターフェイスを定める。
サンプルプログラムではFactoryクラスがこの役をつとめる。
AbstructProduct?役とAbstructFactory?役のインターフェイスだけを使って仕事を行う。
この仕事を行うクラスでは、具体的な部品や製品や工場については知らない。
AbstructProduct?役のインターフェイスを実装する。
AbstructFactory?役のインターフェイスを実装する。
どのようなクラスを作り、どのようなメソッドを作ればいいのかがわかっているから。
逆に不便な点は、新たに部品を追加するのが困難であるとうこと。
Abstruct Factoryパターンはインターフェイスが定まっている抽象的な部品を組み合わせて、
複雑なインスタンスを作る。
Builderパターンは段階を追って大きなインスタンスを作る。
参考資料