@blog.justoneplanet.info

日々勉強

PHPでデザインパターン:FactoryMethod(ファクトリーメソッド)

メリットは「生成と処理を分離し利用側の変更なしに処理(クラス)を追加したりできる」ことである。

■コード

今回使用するのは以下のxmlとcsvファイルの2種類とする。

xml

<data>
    <person>
        <name>John</name>
        <occupation>racer</occupation>
    </person>
    <person>
        <name>Mike</name>
        <occupation>banker</occupation>
    </person>
    <person>
        <name>Nick</name>
        <occupation>runner</occupation>
    </person>
</data>

csv

John,racer
Mike,banker
Nick,runner

template methodで処理の枠だけ定義する。

interface Printer
{
    public function read();
    public function output();
}

以下のCsvFilePrinterクラスとXmlFilePrinterクラスで具体的な処理を記述する。

class CsvFilePrinter implements Printer
{
    private $_filename;
    private $_fh;
    public function __construct($filename)
    {
        $this->_filename = $filename;
    }
    public function read()
    {
        $this->_fh = fopen($this->_filename, 'r');
    }
    public function output()
    {
        print("<table>");
        while($data = fgetcsv($this->_fh)){
            print("<tr>");
            for($i = 0, $n = count($data); $i < $n; $i++){
                print("<td>{$data[$i]}</td>");
            }
            print("</tr>");
        }
        print("</table>");
        fclose($this->_fh);
    }
}
class XmlFilePrinter implements Printer
{
    private $_filename;
    private $_rh;
    public function __construct($filename)
    {
        $this->_filename = $filename;
    }
    public function read()
    {
        $this->_rh = simplexml_load_file($this->_filename);
    }
    public function output()
    {
        print('<table>');
        foreach($this->_rh->person as $person){
            print('<tr>');
            print("<td>{$person->name}</td>");
            print("<td>{$person->occupation}</td>");
            print('</tr>');
        }
        print('</table>');
    }
}

Factory部分

分岐してインスタンスを返すようになっている。

class PrinterFactory
{
    public function getPrinter($filename)
    {
        if(preg_match('/\.csv$/i', $filename)){
            return new CsvFilePrinter($filename);
        }
        elseif(preg_match('/\.xml$/i', $filename)){
            return new XmlFilePrinter($filename);
        }
    }
}

クライアントコード

以下のように中身を意識することなく使用できる。

$printer = new PrinterFactory();
$data = $printer->getPrinter('./dat.xml');
$data->read();
$data->output();
/*
John	racer
Mike	banker
Nick	runner
*/
$data = $printer->getPrinter('./dat.csv');
$data->read();
$data->output();
/*
John	racer
Mike	banker
Nick	runner
*/

コメントはまだありません»

No comments yet.

RSS feed for comments on this post.TrackBack URL

Leave a comment