Factory Methodパターンを実装する場合の注意点

今回の内容はプログラマーにとっては常識な内容かもしれません。完全な僕のうっかりミスでハマってしまったことがあったのでまとめてみました。

Factory Methodパターンとは

まずFactory Methodパターンとは何かと。

Factory Method パターン(ファクトリメソッド・パターン)とは、GoF(Gang of Four; 4人のギャングたち)によって定義されたデザインパターンの1つである。 Factory Method パターンは、オブジェクトの生成をサブクラスに委ねることによって、プログラム内で使用されるインスタンスの型の制約を緩めることを目的とする。

Factory Method パターン – Wikipedia

僕は与えられた引数によって生成するクラスを変えたかったので下記のようなコードを書きました(趣旨だけわかるようにかなり簡素化しています)。

class factory {
  public function __construct( $key ) {
    $className = $key.'Product';
    return new $className();
  }
}
abstract class product {
  public function __construct() {
    〜処理〜
  }
  abstract function read();
}
class carProduct extends product {
  public function move() {
    return '走りましたよ!';
  }
}
// 実行
$factory = new factory( 'car' );
echo $factory->move();

で、「走りましたよ!」と出てほしかったのですが、出たのは「undefined method move〜」というエラー!ハマった!
ここでFactoryクラスにmoveメソッドを加えたらそれが実行される始末。

結局原因は何だったかというと、コンストラクタでインスタンス化したオブジェクトを返そうとしていたところ。コンストラクタって戻り値無いんですよ。

なぜ戻り値が無いのかというと、コンストラクタの戻り値はインスタンスへの参照であり
コンストラクタはインスタンス生成時以外に呼び出されることは無いからです

コンストラクタ

なので、下記のようにFactoryクラスと実行ファイルを修正。

class factory {
  public function __construct() {
  }
  public function getInstance( $key ) {
    $className = $key.'Product';
    return new $className();
  }
}
// 実行
$factory = new factory();
$car = $factory->getInstance( 'car' );
echo $factory->move();

無事、「走りましたよ!」が出力されます。

この記事を書くためにいろいろ調べてて思ったんですが、上記はFactory MethodパターンではなくてFactoryパターン…?まぁ「オブジェクトの生成をサブクラスに委ねる」が成り立ってないし。他にもAbstract Factoryパターンってのもあるみたいですが…???このあたりも勉強が必要ですね…。

  • ブックマーク
  • Feedly

この記事を書いた人

キタジマタカシ

長崎在住、フリーランスのWordPress テーマ / プラグインデベロッパー。 多数のプロダクトをオープンソースで開発・公開しています。現在は WordPress 有料テーマ Snow Monkey を開発・販売しています。