8

Singleton と Registry のパターンは非常に単純で、すぐに理解できましたが、Factory のパターンは、まだ 100% 脳に理解してもらうことができていませんでした。今なら理解できると思います。以下にサンプル コードを書きました。確認して、これが Factory パターンの適切な使用法であるかどうかを教えてください。サンプルはPHPで...

<?php
 /**
 *   Factory.class.php
 */
class Factory {
    public static $_database;
    public static $_cache;
    public static $_session;

    // Build our User object with all it's dependencies  
    public static function makeUserObject()
    {
        $user = new User();
        $user->setDatabaseObject(self::$_database);
        $user->setCacheObject(self::$_cache);
        $user->setSessionObject(self::$_session);
        return $user;
    }

    // other objects will be here someday......
}

/**
 *  User.class.php
 */
class User
{
    public function __construct() { }

    // inject Database Object
    public function setDatabaseObject($databaseConnectionObject)
    {
        $this->_databaseObject = $databaseConnectionObject;
    }

    // inject Cache Object
    public function setCacheObject($cacheObject)
    {
        $this->_cacheObject = $cacheObject;
    }

    // inject Session Object
    public function setSessionObject($sessionObject)
    {
        $this->_sessionObject = $sessionObject;
    }

    // other methods here for User object...........
}

/**
 *  index.php  Main page that puts it all together
 *  assume that classes are autoloaded into this page already
 */
// Set our Database + Cache + Session objects into the Factory Object
Factory::$_database = new Databse();
Factory::$_cache = new Cache();
Factory::$_session = new Session();

// Create our User object
// The factory class will build the User object and inject all
// it's dependencies for us =)
$user = Factory::makeUserObject();

?>

したがって、基本的に、データベース、キャッシュ、およびセッション オブジェクトが作成され (ここには示されていません)、それらが Factory オブジェクトに追加されます。これら 3 つの依存関係のいずれかを必要とする各オブジェクトのファクトリ クラスでメソッドを構築できます。彼らも得るものを設定します。これにより、ファクトリ オブジェクトを使用せずに必要に応じて依存関係を直接注入できるため、個々のクラスをある程度移植可能にすることもできます。これは正しいと思いますか?これが正しいとすれば、これは非常に便利です


更新 # 1

これは、私がここで読んだブログ投稿http://www.potstuck.com/2009/01/08/php-dependency-injection/に基づいています。多くの人が「工場」を調べるように言い続けていますが、それについて読んだことはすべて、この記事を読むまで頭に浮かびませんでしたが、「工場」ではないように見えますか?


UPDATE # 2
ウィキペディア からhttp://en.wikipedia.org/wiki/Factory_object オブジェクト指向コンピューター プログラミングでは、ファクトリ オブジェクトは、他のオブジェクトを作成するためのオブジェクトです。これはコンストラクターの抽象化であり、シングルトン パターンなどのさまざまな割り当てスキームを実装するために使用できます。通常、ファクトリ オブジェクトには、作成できるすべての種類のオブジェクトのメソッドがあります。これらのメソッドは、オプションで、オブジェクトの作成方法を定義するパラメーターを受け取り、作成されたオブジェクトを返します。ファクトリ オブジェクトは、特定の種類のオブジェクトを取得することが、単に新しいオブジェクトを作成するよりも複雑なプロセスである場合に使用されます。ファクトリ オブジェクトは、オブジェクトのクラス (該当する場合) を動的に作成する、オブジェクト プールからクラスを返す、オブジェクトに対して複雑な構成を行う、またはその他のことを決定する場合があります。

結局のところ、これはある意味で「ファクトリーオブジェクト」なのかもしれません...

4

5 に答える 5

6

ここの質問の下から私のコメントを要約して拡張しました

他の人が言ったように、この名前のパターンが存在しないという理由だけで、それはFactoryではありません。これはAbstractFactoryまたはFactoryMethodのいずれかですが、実用的には、単にFactoryと言うだけでどちらかまたはどちらかを指すことが多く、それで問題ありません。

セッション、キャッシュ、および DB は通常、アプリケーション フローの早い段階で初期化するものであるため、これは基本的にブートストラップ作業です。あなたが探しているのは、オブジェクトの作成ではなく、アプリケーション全体での処理であるという印象を受けました。これは、 FactoryWhateverが行うこととは多少異なります。

コメントで言ったように、正確にFactoryWhateverではないからといって、コードが悪いというわけではありません。それがあなたの問題を解決するなら、それはクールです。しかし、実行時にリソースを作成および管理するなど、あなたがやろうとしていることは、 DI Service Containerで使用するのが最適だと思います。

これに DI コンテナーを使用したくない場合は、 Zend_Application と、リソースのブートストラップ方法を参照してください。これは代替手段であり、後で DI コンテナーを追加する可能性を残しています。

実際、以前の質問のトピックのかなりの部分は、Zend Framework で既に解決されています (例: Config クラス)。ZF を使用すると言っているわけではありませんが、ZF がどのように動作するかを確認できます。もちろん、他の フレームワークも見ることができます。

PHP の例を含むいくつかのパターン サイト:

于 2010-01-26T10:15:31.603 に答える
5

これはファクトリパターンで問題ありませんが、単に呼び出すよりも優れた命名規則が必要になる場合がありますFactory。また、依存性注入の痕跡も含まれています。

技術的にはファクトリパターンと呼ぶこともできますが、パターンの適切な使用法ではない可能性があります。Factoryは、正確なコンストラクターパラメーターなどのようにクラス名とオブジェクト作成を直接参照することからコードをカプセル化する作成パターンです。最良の結果を得るには、クラスとファクトリを設計するときにそのことを念頭に置いてください。

たとえば、StackOverflowは、レピュテーションスコアに応じてユーザーにさまざまな権限を付与します。仮に、次のタイプのユーザーがいる可能性があります。

NewbieUser      [1-100]
BeginnerUser    [101-1000]
AverageJoeUser  [1001-5000]
VeteranUser     [5001-20000]
PowerUser       [20001-50000]
GodModeUser     [50001-100000]

担当者を検索することでユーザーを作成できます。クラスを直接参照することにより、対応するユーザーオブジェクトをインスタンス化します。不思議に思うかもしれませんが、JonSkeetはどのカテゴリにも表示されません。これは、直接インスタンス化された安っぽい実装です。

if(reputation >= 1001 and reputation <= 5000) {
    AverageJoeUser user = new AverageJoeUser();
}

後でクラス名やユーザーのインスタンス化方法を変更する場合は、オブジェクトが作成されたそのようなインスタンスをすべて見つけて変更する必要があります。あなたが私に尋ねれば、かなり多くの仕事があります。代わりに、ここでFactoryパターンを使用した場合、変更はFactoryクラス内の単一のメソッドで行われます。

class UserFactory {
    public static User createUser(Integer reputation) {
        ...
    }
}
于 2010-01-26T09:51:03.227 に答える
3

私には工場のようには見えません - 裏返しのビルダーかもしれません?;0)

Factory は、実装とインスタンス化を隠す方法です。そして、通常、いくつかの組み立てが行われますが、一言で言えば....

  public interface IUser
    {
        void DoSomething();
    }

    public class DumbUser : IUser
    {

        public void DoSomething()
        {
            // duh... what should i do?
        }

    }

    public class SmartUser : IUser
    {

        public void DoSomething()
        {
            // calclulating prime numbers while baking bread
        }

    }


    public class UserFactory
    {
        public static IUser CreateUser()
        {
            Random r = new Random(Environment.TickCount);

            return r.Next(10) > 5 ? (IUser) new SmartUser() : new DumbUser();
        }
    }

    public class YourProgram
    {
        public void Run()
        {
            IUser user = UserFactory.CreateUser();
            user.DoSomething();
        }
    }
于 2010-01-26T09:31:12.430 に答える
2

単にユーザーを作成したいように思われるので、抽象的な要素(以降、単にファクトリと呼びます)の必要性はわかりません。ファクトリのアイデアは、特定のインターフェイスを実装するオブジェクトを作成することです。同じインターフェースの2つの異なる実装をインスタンス化できるようにする必要があります。重要なのは、これらのオブジェクトを何度も作成する必要があり、コード全体でObjectAからObjectBに変更するのは面倒なことです。工場はシングルトンであることが多いため、工場の交換は簡単です。

ファクトリメソッドのアイデアはフレームワークに関連しています。フレームワークコードで使用法を作成したいのですが、実際のユーザー実装は派生クラスにあります。つまり、フレームワークのユーザーが独自のアプリを作成している場合です。フレームワークのユーザーは、ファクトリメソッドの呼び出しである「ユーザーオブジェクトを今すぐ作成」します。ユーザーはこれを実装する必要があります。GoFによると、仮想コンストラクターとも呼ばれます。

ビルダーは通常、オブジェクトのさまざまな表現がある場合に使用されますが、ここでは実際にはそうではありません。私の目には、キャッシュ、データベース、およびセッションをシングルトンとして実装できるため、複雑な作業が軽減されます。GetDatabaseそれ以外の場合は、などを実行できるServiceLocatorを使用することをお勧めしますGetSession。次に、作成時にロケーターをユーザーオブジェクト(および他の多くのオブジェクト)に渡す必要があります。利点は、このロケーターをさまざまなクラスで再利用できることです。

于 2010-01-26T09:49:17.370 に答える
1

私にはビルダーパターンのように見えます。実際には、AbtractFactory と FactoryMethod のどちらのファクトリ パターンを意味していましたか? ただし、どちらも継承を処理し、コードは「複雑な」オブジェクトをアセンブルするだけです。

于 2010-01-26T09:23:33.220 に答える