PHPのファクトリデザインパターンとは何ですか?


88

これは私を混乱させます、最も簡単な言葉でそれは何をしますか?お母さんや誰かに説明しているふりをしてください。


115
私の母は...とにかくそれを理解できないだろう
ブルーノ・レイス

6
@JasonDavis私はあなたの質問に答え続けます...私はストーカーのように感じ始めています。
タイラーカーター

回答:


175

ファクトリはオブジェクトを作成します。だから、あなたが構築したい場合

 class A{
    public $classb;
    public $classc;
    public function __construct($classb, $classc)
    {
         $this->classb = $classb;
         $this->classc = $classc;
    }
  }

オブジェクトを作成するたびに次のコードを実行する必要があることに依存したくないでしょう。

$obj = new ClassA(new ClassB, new Class C);

そこで工場が登場します。私たちはそれを処理する工場を定義します。

class Factory{
    public function build()
    {
        $classc = $this->buildC();
        $classb = $this->buildB();
        return $this->buildA($classb, $classc);

    }

    public function buildA($classb, $classc)
    {
        return new ClassA($classb, $classc);
    }

    public function buildB()
    {
        return new ClassB;
    }

    public function buildC()
    {
        return new ClassC;
    }
}

今私たちがしなければならないのは

$factory = new Factory;
$obj     = $factory->build();

本当の利点は、クラスを変更したいときです。別のClassCを渡したいとしましょう。

class Factory_New extends Factory{
    public function buildC(){
        return new ClassD;
    }
}

または新しいClassB:

class Factory_New2 extends Factory{
    public function buildB(){
        return new ClassE;
    }
}

これで、継承を使用して、クラスの作成方法を簡単に変更し、別のクラスのセットを配置できます。

良い例は、次のユーザークラスです。

class User{
    public $data;
    public function __construct($data)
    {
        $this->data = $data;
    }
}

このクラスに$dataは、データを格納するために使用するクラスがあります。このクラスでは、セッションを使用してデータを保存するとします。工場は次のようになります。

class Factory{
    public function build()
    {
        $data = $this->buildData();
        return $this->buildUser($data);
    }

    public function buildData()
    {
        return SessionObject();
    }

    public function buildUser($data)
    {
        return User($data);
    }
}

ここで、代わりにすべてのデータをデータベースに保存したいとします。変更するのは本当に簡単です。

class Factory_New extends Factory{
    public function buildData()
    {
        return DatabaseObject();
    }
}

ファクトリは、オブジェクトを組み合わせる方法を制御するために使用するデザインパターンであり、正しいファクトリパターンを使用すると、必要なカスタマイズされたオブジェクトを作成できます。


3
それはたくさんのタイピングでした。今、私はそれをいつか私のウィキに載せなければならないでしょう。
タイラーカーター

1
素敵で親切。あなたの仲間に帽子をかぶる。
stefgosselin

1
コードの違い/利点は$obj = $factory->build();$obj = new whateverClass();ですか?また、classAのデータに依存する別のクラス(たとえばclassZ)では、classZのどこでファクトリメソッドを使用しますか?基本的に、クラス(classA)内でクラス(classZ)をインスタンス化しています。つまり、テストは行われません。たとえば、ファクトリnewは、を使用するだけでなく、メソッドを介して実行するコードの負荷のようですnew
ジェームズ

19

実際の工場のように、何かを作成して返します。

このようなものを想像してみてください

$joe = new Joe();
$joe->say('hello');

またはファクトリメソッド

Joe::Factory()->say('hello');

ファクトリメソッドの実装は、新しいインスタンスを作成して返します。


1
良い例ですが、このパターンの実装がどれほど多様であるかを驚かせます。静的に呼び出された場合、後で同じインスタンスを再利用するためにインスタンスへの参照を取得できると思いますか?つまり、$ joe = Joe :: Factory()-> say( 'hello');
stefgosselin

確かに5.6と同じように、(new Joe())-> say( 'hello');も実行できます。
パンチョ

12

複数のリソースを処理していて、高レベルの抽象化を実装したい場合、ファクトリデザインパターンは非常に優れています。

これを別のセクションに分けてみましょう。

抽象化を実装する必要があり、クラスのユーザーがクラス定義に実装したものを気にする必要がないとします。

彼/彼女はあなたのクラスメソッドの使用について心配する必要があるだけです。

たとえば、プロジェクトに2つのデータベースがあります

class MySQLConn {

        public function __construct() {
                echo "MySQL Database Connection" . PHP_EOL;
        }

        public function select() {
                echo "Your mysql select query execute here" . PHP_EOL;
        }

}

class OracleConn {

        public function __construct() {
                echo "Oracle Database Connection" . PHP_EOL;
        }

        public function select() {
                echo "Your oracle select query execute here" . PHP_EOL;
        }

}

Factoryクラスは、データベース接続用のオブジェクトの作成を処理します。

class DBFactory {

        public static function getConn($dbtype) {

                switch($dbtype) {
                        case "MySQL":
                                $dbobj = new MySQLConn();
                                break;
                        case "Oracle":
                                $dbobj = new OracleConn();
                                break;
                        default:
                                $dbobj = new MySQLConn();
                                break;
                }

                return $dbobj;
        }

}

ユーザーはデータベースタイプの名前を渡すだけです

$dbconn1 = DBFactory::getConn("MySQL");
$dbconn1->select();

出力:

MySQL Database Connection
Your mysql select query execute here

将来、データベースが異なる可能性があります。コード全体を変更する必要はなく、新しいデータベースタイプを渡すだけで、他のコードは変更せずに実行されます。

$dbconn2 = DBFactory::getConn("Oracle");
$dbconn2->select();

出力:

Oracle Database Connection
Your oracle select query execute here

これがお役に立てば幸いです。


1

一般に、「ファクトリ」は何かを生成します。オブジェクト指向プログラミングの場合、「ファクトリデザインパターン」はオブジェクトを生成します。

PHP、C#、またはその他のオブジェクト指向言語であるかどうかは関係ありません。


1

ファクトリデザインパターン(ファクトリパターン)は、疎結合用です。工場の意味と同様に、工場へのデータ(データの生成)から最終ユーザーへ。このようにして、工場はデータのソースとデータのプロセスの間の緊密な結合を断ち切ります。



0

この回答は、ダニエルホワイトがファクトリパターンを使用してMySQL接続を作成するためにファクトリを使用すると述べた他の投稿に関連しています。

MySQL接続の場合、データベースへのアクセスに同じ接続を使用し、別の接続を作成しないため、シングルトンパターンを使用します。


0

オブジェクトをインスタンス化するための古典的なアプローチは次のとおりです。

$Object=new ClassName();

PHPには、次の構文を使用して変数名からオブジェクトを動的に作成する機能があります。

$Object=new $classname;

ここで、変数$ classnameには、インスタンス化するクラスの名前が含まれています。

したがって、古典的なオブジェクト因数分解は次のようになります。

function getInstance($classname)
{
  if($classname==='Customer')
  {
    $Object=new Customer();
  }
  elseif($classname==='Product')
  {
    $Object=new Product();
  }
  return $Object;
}

getInstance( 'Product')関数を呼び出すと、このファクトリはProductオブジェクトを作成して返します。それ以外の場合、getInstance( 'Customer')関数を呼び出すと、このファクトリはCustomerタイプのオブジェクト(Customer()クラスから作成)を作成して返します。

これ以上の必要はありません。動的インスタンス化の変数の値として「Product」または「Customer」(既存のクラスの正確な名前)を送信できます。

$classname='Product';
$Object1=new $classname; //this will instantiate new Product()

$classname='Customer';
$Object2=new $classname; //this will instantiate new Customer()

0

ちなみに、簡単に言うと、@ Pindatjuhのようなファクトリはオブジェクトを返します。

では、コンストラクターとの違いは何ですか?(それは同じことをします)

  1. コンストラクターは自分のインスタンスを使用します。
  2. もっと高度なものにしたいので、オブジェクトを肥大化させたくない(または依存関係を追加したくない)。
  3. コンストラクターは、各インスタンスが作成されるときに呼び出されます。時々あなたはそれを望まない。

    たとえば、Accountクラスのオブジェクトを作成するたびに、データベースからファイルを読み取り、それをテンプレートとして使用するとします。

コンストラクターの使用:

class Account {
      var $user;
      var $pwd;
      var ...
      public __construct() {
         // here i read from the file
         // and many other stuff
      }
}

工場の使用:

class Account {
      var $user;
      var $pwd;
      var ...
}
class AccountFactory {
      public static Create() {
         $obj=new Account();
         // here we read the file and more stuff.
         return $obj;
      }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.