3

抽象ファクトリでは、オブジェクトの作成を担当する型を宣言します。

これにより、次のようなスイッチが不要になります。

 if( type == ONE ) {
     doOne();
  } else if( type == TWO ) { 
     doTwo();
  } etc. 

または同じ:

 switch( type ) {
     case ONE: doOne(); break;
     case TWO: doTwo(); break;
     etc....
  }

これに:

   MyAbstractFactory factoryInstance = ... ? 

   SomeObject object = factoryInstance.createObject();

   object.doX();

私が理解しているように、AbstractFactoryは正しいオブジェクトを作成し、それが多形的に正しい動作を実行します。

次に、そのオブジェクトをプログラムで10〜20回または100回使用する場合、毎回切り替えを繰り返す必要はありません。対応するメソッドを実行し、ポリモーフィズムに任せてください。

   object.doY();

   object.doZ();

新しいタイプの追加は、新しいコンクリート工場を作成するのと同じくらい簡単です。

これはすべて私には明らかです。だが...

そもそもコンクリート工場はどこで、どのように(一般的に)作られているのでしょうか?

私は常に1つのポイント(通常はmain()メソッドまたはConfiguration.init()メソッド)を使用してきましたが、これには避けられないif / else | switch構文がありますが、少なくとも1回だけ使用されます。

しかし、私はこれを「本能的に」(または常識的に)行いましたが、パターンがどこで作成されるべきかを説明しているドキュメントを読んだことはありませんでした。

:)

4

5 に答える 5

1

抽象ファクトリの主な利点は、どの具象アイテムがファクトリによって作成されているかという知識をファクトリのクライアントから分離していることにあるため、その知識 (および明らかに具象ファクトリの実装を含む) を他のものから遠ざける必要があります。コードの。これを行う 1 つの方法は、実行時に抽象的なファクトリ インスタンスへのアクセスを提供する「FactoryService」を作成することです。

クライアント コードは次のようになります。

FactoryService service = FactoryService.instance();
MyAbstractFactory factory = service.getFactory();
SomeObject obj = factory.createObject();

このようにして、ファクトリをインスタンス化するロジックをサービス内に隠し、サービスは、たとえば、構成ファイルからクラス名を読み取ることができます。

多くのフレームワークには、コンポーネントの作成とその依存関係の設定を可能にするコンポーネント ライフサイクル管理があります (前述のように、Spring はその 1 つです)。Spring ベースにしたい場合は、ファクトリーの特定のインスタンスをファクトリー サービスに注入するように Spring を構成できます。

この方法のもう 1 つの利点は、テスト容易性です。テスト ランナーを構成して、モック ファクトリを作成し、それをサービスに挿入できます。サービスのすべてのユーザーは、コードを変更することなく、テスト目的で使用されるこのモック ファクトリを受け取ります。

于 2009-07-22T17:53:37.827 に答える
1

Abstract Factoryは、工場のための工場のようなものです。具体的な型を知らなくても、関連するオブジェクトを作成する方法を提供します。どの「抽象ファクトリ」を「インスタンス化」するかを知る必要があります。これは、抽象ファクトリのどの具体的な実装を、変数に基づいてインスタンス化することを意味します。

たとえば、あなたが車/トラックのメーカーで、CarSeatsCarStereoなどのアイテムがあり、 TruckSeats 、 TruckStereo もあるます。これらはすべて、IVehicleItemと言う共通のインターフェースを実装しています。この時点で、抽象ファクトリを実装する2 つのファクトリTruckFactoryCarFactoryを持つことができます ( VehicleFactoryなど) 。これで、このようなことができます。

VehicleFactory carFactory = new CarFactory();
IVehicle car = new Car(carFactory);

VehicleFactory truckFactory = new TruckFactory();
IVehicle truck = new Truck(truckFactory);

ご覧のとおり、必要なときに適切なファクトリをインスタンス化しています。これは現時点で私が思いつく最良の例ですが、switch ステートメントやファクトリ クラスの if ステートメントはまったく悪いとは思いません。私は通常、必要なクラスを把握するために Enum を使用します。

編集して追加:混乱は、Abstract Factory とは何かを人々が誤解していると思います。多分それは私の「反対票」の場合です。 抽象ファクトリ パターンは、ファクトリ メソッド パターンとは異なります。

Wiki - 抽象ファクトリ パターンは、ファクトリ パターンとインターフェイス パターンの使用を組み込んだ複合パターンです。

あなたは、WikiやGoFなどではなく、具象クラスをインスタンス化する方法を示していると述べています。これは正しくありません。ウィキペディアの Factory Method Pattern の記事を見ると、この小さなスニペットが表示されます。

public static ImageReader getImageReader(InputStream is) {    

 int imageType = figureOutImageType(is);

   switch(imageType) {
            case ImageReaderFactory.GIF:
                return new GifReader(is);
            case ImageReaderFactory.JPEG:
                return new JpegReader(is);
            // etc.
        }
}

Abstract Factory パターンに関するウィキペディアの記事を読むと、この小さなコード スニペットが表示されます。

public static GUIFactory createOsSpecificFactory() {
        int sys = readFromConfigFile("OS_TYPE");
        if (sys == 0) {
            return new WinFactory();
        } else {
            return new OSXFactory();
        }
    }

ポイントは、「正しい」方法がないということです。アプリケーションで何をしようとしているかに基づいて、具象クラスをインスタンス化します。確かに「if」または「switch」ステートメントは避けられます。しかし、個人的には、それらを使用することに問題はないと思います。

于 2009-07-22T16:44:58.400 に答える
0

AbstractFactory を使用している場合、2 つのシナリオがあることがわかりました。

1 つ目は、オブジェクトの実行に 1 つの具象クラスのみが使用される場合です。これの標準的な例は、データベース アクセス コードです。SQL Server で DB にアクセスしてから、突然 Oracle に切り替えることはありません。具体的なクラスは安定しています。そのために、Provider モデルを使用します。ProviderBase クラス、ProviderCollection クラスなどを定義します。

もう 1 つのシナリオは、具象クラスがアプリケーションの状態に依存する場合です。その場合、私は通常、適切な具象クラスを返す抽象基本クラスにファクトリ メソッドを提供します。そのメソッド内には、インスタンス化する具象クラスを決定するための switch ステートメントが通常あります。他の誰かが提案したことを試して、すべての具象クラスのコピーをコレクションに保存しましたが、その特定のアプリケーションでは、その時点でそれらのクラスすべてをインスタンス化するパフォーマンスは受け入れられませんでした。ただし、これらの選択はどちらも完全に有効であり、実装がかなり簡単です。

于 2009-07-22T18:15:04.380 に答える
0

このインスタンスで IoC フレームワークを使用するのが最も柔軟なソリューションです。Spring は以前の回答で推奨されていましたが、Google Guice も優れた選択肢であり、非常に簡単に開始できます。

ただし、純粋な Java ソリューションが必要な場合は、列挙型が非常にうまく機能します。次の例を検討してください。

enum FactoryConfig {
  CONFIG_1 {
     IFactory instantiate() {
        return ...
     }
  },
  CONFIG_2 {
     IFactory instantiate() {
        return ...
     }
  },
  CONFIG_3 {
     IFactory instantiate() {
        return ...
     }
  };

  abstract IFactory instantiate();
}
...
// and its usage..

IFactory factory = FactoryConfig.CONFIG_3.instantiate();

列挙型の同様の使用法については、たとえばhereおよびhereを参照してください。

于 2009-07-22T19:43:58.413 に答える