0

現在、現在の PHP 5.2 プロジェクトでオブジェクトを作成する最善の方法を見つけようとしています。基本的に、キーでオブジェクトを返すレジストリがあります。指定されたキーを持つオブジェクトがレジストリにない場合、構築によってレジストリに提供されるファクトリ メソッドを呼び出して、オブジェクトを作成しようとします。次のコードを見てください。

interface IFactory
{
    public function createProduct( $key );
}

class Registry
{
    private $m_elements = array( );
    private $m_factory;
    public function __construct( IFactory $factory )
    {
       $this->m_factory = $factory;
    }
    public function getElement( $key )
    {
      if ( !array_key_exists( $key, $this->m_elements ) )
      {
          $this->m_elements[$key] = $this->m_factory->createProduct( $key );
      }
      return $this->m_elements[$key];
    }
}

さまざまなレジストリに保存したいさまざまなオブジェクトのカテゴリがあるため、次のように、レジストリオブジェクトをカテゴリごとにシングルトンにラップします。

class SpecialRegistry
{
   private static $instance = null;

   public static function getInstance( )
   {
       if( self::$instance === null )
       {
           self::$instance = new Registry( new SpecialFactory( ) );
       }
       return self::$instance;
   }
}

私の Special クラスはかなり複雑で大きく、さまざまな属性と構成オブジェクトがたくさんあります。Special クラスを特定のバックエンドにバインドしたくないので、異なるバックエンド (MySQL データベースやファイル ストリームなど) ごとに異なるファクトリを用意しました。そのため、読み込みと初期化のロジックをファクトリに移動します。ただし、これは Special クラスのすべてのフィールドが Factory に対して public である場合にのみ機能します。ただし、アプリケーションの残りの部分に対して公開するべきではありません。

C++ では、フレンドを使用してこの問題を回避できます。また、スタック オーバーフローについても、ほぼ同じトピックを読みましたが、C# に適用されました。すべてのフィールドを Special クラスで public に設定し、Factory は、アプリケーションに対して public にしたいメソッドと属性を公開する Interface のみを返すようにする必要があるとのことでした。しかし、PHP は戻り型のヒントをサポートしていないため、Special クラスが実装するインターフェイスだけを返すことはできません。私が思いついた別の方法は、実際に SpecialFactory を Special クラスから継承させて、ファクトリからプライベートおよび保護されたフィールドにアクセスできるようにすることです。これは、工場が独自の製品を継承しているため、私が「バスタードファクトリー」と呼んだものです.

誰かが私が望むものを達成するためのより良い方法を思いつくことができるかどうか知りたい. それとも、私は完全に軌道から外れており、工場に初期化プロセスを任せることは絶対にありませんか? 皆さんの意見が気になります!

4

1 に答える 1

1

Java のバックグラウンドから来て、そこにビルダーを追加するのはどうですか? このビルダーは、ファクトリが構築できるパブリック フィールドを介してその状態を公開できます。ビルダーが完成したら、それを Special クラスに渡し、ビルダーからその状態をロードします。

あなたの工場でこのようなもの(疑似コード):

public function createProduct() {
  SpecialBuilder builder = new SpecialBuilder();
  // Do whatever you would have done to the Special class to the builder
  // ...
  Special special = new Special(builder);
  return special;
}

このようにして、Special オブジェクトは内部状態を隠すことができます。私が見る唯一の実際の欠点は、オブジェクトの過負荷のわずかなケースであることです。

于 2010-07-29T10:46:52.980 に答える