PHPで使うGoFパターン ひとり Advent Calendar - ファクトリメソッド


上げるのをすっかり忘れておりました。
申し訳ないです。

## ファクトリメソッドってなに?
これも生成に関するパターンですね要するにオブジェクトを new する + α の「そのオブジェクトを使える状態にする」処理をメソッドに追い出すパターンです。煩雑な生成処理を至るところに書かなくても済むようになり、さらにクラス間の依存を弱めることが出来ます。

## ファクトリメソッドの構造

* Facotry - 生成をファクトるクラスです
* IProduct - ファクトられるクラスのインターフェースです。これは抽象クラスでも、実クラスでも、インターフェースでも良いです
* Product - 実クラスです

```
<?php
abstract class ModelFactoryBase {
  public function __contruct () {
  }
  public function create ($name) {
     $class = "${name}Entity";
     if (!class_exists($class)) {
       require "$class.php";
     }
     $obj = new $class;
     $this->prepareObject($obj);
     return $obj;
  }
  // これがファクトリメソッド
  public abstract function prepareObject($obj);
}

class ModelFactoryDqnProperty extends ModelFactoryBase{
    public function prepareObject ($obj) {
        // プロパティ を設定する以外にも、この手のファクトリメソッドであれば
        // XMLの配信先やCSVの保存先を切り替えたりしても良い
        $obj->default1 = get_class($obj) . '|ヽ(゜▽、゜)ノ1';
        $obj->default2 = get_class($obj) . '|ヽ(゜▽、゜)ノ2';
        $obj->default3 = get_class($obj) . '|ヽ(゜▽、゜)ノ3';
        $obj->default4 = get_class($obj) . '|ヽ(゜▽、゜)ノ4';
        $obj->default5 = get_class($obj) . '|ヽ(゜▽、゜)ノ5';
    }
}

class ModelFactoryFillDefaultProperty extends ModelFactoryBase {
    public function prepareObject ($obj) {
        $obj->default1 = get_class($obj) .'|default1';
        $obj->default2 = get_class($obj) .'|default2';
        $obj->default3 = get_class($obj) .'|default3';
        $obj->default4 = get_class($obj) .'|default4';
        $obj->default5 = get_class($obj) .'|default5';
    }
}


abstract class ModelBase {
    private $value = array ();
    public function __get ($key) {
        if (isset($this->value[$key])) return $this->value[$key];
        else                           return null;
    }

    public function __set ($key, $value) {
        $this->value[$key] = $value;
    }

    abstract function find ($id);
    abstract function save ();
    abstract function delete ();
}

class CSVEntity extends ModelBase {
    public function find ( $id ) {
        // CSVを読み込んで自身を満たす
        // $f = fopen ( '/path/to/data' );
        // fgetcsv ( $f );
        // ごにょごにょ
    }

    public function save () {
        // CSVに自身のデータを保存する
    }

    public function delete () {
        // CSVからIDのレコードを削除
    }

}

class XMLEntity extends ModelBase {
    public function find ( $id ) {
        // XMLを読み込んで自身を満たす
        // $xml = simplexml_load_file ( '/path/to/data' );
        // ごにょごにょ
    }


    public function save (){
        // XMLに自身のデータを保存する
    }

    public function delete () {
        // XMLからIDのレコードを削除
    }
}

$factory = new ModelFactoryDqnProperty();
$xml = $factory->create ( 'XML' );
$csv = $factory->create ( 'CSV' );
$xml->find (1);
$csv->find (1);

print '<< DQN >>' . "\n";
print 'XML->default1 = ' . $xml->default1 . "\n";
print 'CSV->default1 = ' . $csv->default1 . "\n";

$factory = new ModelFactoryFillDefaultProperty();
$xml = $factory->create ('XML');
$csv = $factory->create ('CSV');
$xml->find (1);
$csv->find (1);

print '<< DefaultProps >>' . "\n";
print 'XML->default1 = ' . $xml->default1 . "\n";
print 'CSV->default1 = ' . $csv->default1 . "\n";

```

というような感じです。