[ PHP ] Abstract Factory パターンの実装サンプル

Pocket

ここでは、Abstract Factory パターンの PHP における実装サンプルを紹介しています。そもそも Abstruct Factory パターンとは、 ウィキペディア:Abstract Factory パターン では、

Abstract Factory パターンとは、関連するインスタンス群を生成するための API を集約することによって、複数のモジュール群の再利用を効率化することを目的とする。 日本語では「抽象的な工場」と翻訳される事が多い。

と説明がされていますが、プログラマー以外には意味不明です。

スポンサーリンク


PHP による Abstract Factory パターンの実装例

以下は、データベースの接続および切断を行う抽象クラスになります。この抽象クラスの中身をそれぞれのデータベースごとに実装していくことになります。

// データベースへの接続と切断を定義する抽象クラス
abstract class Database_Abstract
{
    protected $_connection;

    // データベースへの接続
    abstract public function openConnection();
    
    // データベースから切断
    abstract public function closeConnection();
}

次に、上記の抽象クラスを派生させ、Oracle および Mysql への接続と切断を行うクラスを実装します。

Oracle への接続と切断の実装例

class Oracle_Database extends Database_Abstract
{
    static public function CreateFactory()
    {
        return new Oracle_Database();
    }
    
    public function openConnection()
    {
       // oracle データベースに接続する処理
       $this->_connection = $oci_connect('パラメータ', ・・・);
    }
    
    public function closeConnection()
    {
        oci_close($this->_connection);
        $this->_connection = null;    
    }
}

Mysql への接続と切断の実装例

class Mysql_Database extends Database_Abstract
{
    static public function CreateFactory()
    {
        return new Mysql_Database();
    }
    
    public function openConnection()
    {
       // Mysql データベースに接続する処理
       $this->_connection = mysqli_init();
       mysqli_real_connect('パラメータ', ・・・);
    }
    
    public function closeConnection()
    {
        $this->_connection->close();
        $this->_connection = null;
    }
}

使用例

上記で実装した各々のデータベース接続クラスは次のようにインスタンスの生成を行います。


if($db == 'oracle') {
    // oracle への接続と切断
    $factory = Oracle_Database::CreateFactory();
} else if($db == 'mysql') {
    // Mysql への接続と切断
    $factory = Mysql_Database::CreateFactory();
}

/*
 * 以降、データベースの違いを意識することはない
 */
// データベースへ接続
$factory->openConnection();

// データベースから切断
$factory->closeConnection();

ポイント

インスタンスの生成は派生クラスで実装した CreateFactory 静的メソッドの1か所で集約しています。そのため、ユーザーが Oracle への接続時の場合は、Oracle_Database::CreateFactory で返されるインスタンスを使用するというルールを順守する限り、誤って Mysql へ接続することを防止できます。

次に Oracle, Mysql それぞれの接続および切断は同一の呼び出し方法(メソッド)で実現可能であり、それぞれの実装を使用する側はデータベースごとの違いを意識する必要がありません。

問題点としては、同一のメソッド(ルール)で同一機能を実現するためには、機能(抽象クラスの抽象メソッド)が 増えると、すべての派生クラスの修正が必要であり、場合によっては呼び出し側の修正も必要となる点です(ライブラリ作成者としては億劫な気分になるときもあります)。

今回のサンプルでは、抽象クラスのメソッドには、接続と切断の機能だけを持つようにしていますが、抽象クラスではなくインターフェースでの定義に変更しても同じす。

データベースによって、各機能について対応していない場合には、例外を飛ばすような実装もあります。

 

スポンサーリンク

Pocket

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>