5

抽象ファクトリ パターンを使用する必要がある場合を知りたいです。

ここに例がありますが、必要かどうか知りたいです。

UML

上記は抽象ファクトリのパターンで、クラスメートが推奨しています。以下は私自身の実装です。パターンを使用する必要はないと思います。

そして、以下はいくつかのコアコードです:

    package net;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;



public class Test {
    public static void main(String[] args) throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException {
        DaoRepository dr=new DaoRepository();
        AbstractDao dao=dr.findDao("sql");
        dao.insert();
    }
}

class DaoRepository {
    Map<String, AbstractDao> daoMap=new HashMap<String, AbstractDao>();
    public DaoRepository () throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException  {
        Properties p=new Properties();
        p.load(DaoRepository.class.getResourceAsStream("Test.properties"));
        initDaos(p);
    }
    public void initDaos(Properties p) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        String[] daoarray=p.getProperty("dao").split(",");
        for(String dao:daoarray) {
            AbstractDao ad=(AbstractDao)Class.forName(dao).newInstance();
            daoMap.put(ad.getID(),ad);
        }
    }
    public AbstractDao findDao(String id) {return daoMap.get(id);}

}
abstract class AbstractDao {
    public abstract String getID();
    public abstract void insert();
    public abstract void update();
}
class SqlDao extends AbstractDao {
    public SqlDao() {}
    public String getID() {return "sql";}
    public void insert() {System.out.println("sql insert");}
    public void update() {System.out.println("sql update");}
}
class AccessDao extends AbstractDao {
    public AccessDao() {}
    public String getID() {return "access";}
    public void insert() {System.out.println("access insert");}
    public void update() {System.out.println("access update");}
}

Test.properties の内容はたった 1 行です。

dao=net.SqlDao,net.SqlDao

それで、このスーツが必要かどうかを教えてくれる人はいますか?


-------------------実際のスーツを説明するために以下を追加します--------------

Dao の例を使用するのは、それが一般的であり、誰もが知っているからです。

実は、私が今取り組んでいることはDAOとは関係なく、Webを構築する仕事をしています

サービス、Web サービスには、ファイルを他の形式に変更するためのいくつかのアルゴリズムが含まれています。

たとえば、net.CreatePDF、net.CreateWord などで、getAlgorithms と doProcess の 2 つのインターフェイスをクライアントに公開します。

getAlogrithoms はすべてのアルゴリズムの ID を返します。各 ID は対応するアルゴリズムに関連付けられます。

doProcess メソッドを呼び出すユーザーは、必要なアルゴリズム ID も提供します。

すべてのアルゴリズムは、run() メソッドを定義する AbstractAlgorithm を拡張します。

私はすべてのアルゴリズムを格納するために AlogrithmsRepository を使用します (から

Web によるアルゴリズムの具体的な Java クラスを構成するプロパティ ファイル

つまり、Web サービスによって公開されるインターフェイス DoProcess は

具体的なアルゴリズムによって実行されます。

簡単な例を挙げることができます: 1) ユーザーは getAlgorithms リクエストを送信します:

http://host:port/ws?request=getAlgorithms

次に、ユーザーは xml に埋め込まれたアルゴリズムのリストを取得します。

<AlgorithmsList>
  <algorithm>pdf</algorithm>
  <algorithm>word<algorithm>
</AlgorithmsList>

2) ユーザーは次の方法で DoProcess をサーバーに送信します。

http://xxx/ws?request=doProcess&alogrithm=pdf&file=http://xx/Test.word

サーバーがこのタイプのリクエストを受け取ると、AlgorithmRepostory から「algorithm」パラメーター (このリクエストでは pdf) に従って具体的なアルゴリズム インスタンスを取得します。そしてメソッドを呼び出します:

AbstractAlgorithm algo=AlgorithmRepostory.getAlgo("pdf");
algo.start();

その後、pdf ファイルがユーザーに送信されます。

ところで、この例では、各アルゴリズムは sqlDao、AccessDao に似ています。画像は次のとおりです。

デザインイメージ

さて、AlgorithmRepostory は Abstract Factory を使用する必要がありますか?

4

3 に答える 3

2

2 つのアプローチの主な違いは、上のアプローチでは異なる DAO ファクトリを使用して DAO を作成するのに対して、下のアプローチでは一連の DAO を格納し、リポジトリ内の DAO への参照を返すことです。

JDBC接続が同期されていないため、複数のスレッドが同じタイプのDAOに同時にアクセスする必要がある場合、下のアプローチには問題があります。

newInstance()これは、単純に新しい DAO を作成して返すメソッドをDAO に実装させることで修正できます。

abstract class AbstractDao {
    public abstract String getID();
    public abstract void insert();
    public abstract void update();
    public abstract AbstractDao newInstance();
}
class SqlDao extends AbstractDao {
    public SqlDao() {}
    public String getID() {return "sql";}
    public void insert() {System.out.println("sql insert");}
    public void update() {System.out.println("sql update");}
    public AbstractDao newInstance() { return new SqlDao();}
}

リポジトリは、次のように、リポジトリから返された DAO のファクトリとしてリポジトリ内の DAO を使用できます (その場合は名前を Factory に変更します)。

public AbstractDao newDao(String id) {
    return daoMap.containsKey(id) ? daoMap.get(id).newInstance() : null;
}

アップデート

あなたの質問については、あなたのWebサービスはファクトリを実装する必要がありますか、それともあなたが説明したようにリポジトリを使用できますか? 繰り返しますが、答えは詳細によって異なります。

  • Web サービスの場合、複数の同時クライアントが予想されるのが普通です
  • したがって、2 つのクライアントのプロセスを実行するインスタンスが互いに影響を与えてはなりません
  • つまり、状態を共有してはいけません
  • ファクトリはリクエストごとに新しいインスタンスを提供するため、ファクトリ パターンを使用すると状態は共有されません
  • リポジトリ内のインスタンスがステートレスである場合 (およびその場合のみ)、Web サービスは説明どおりにリポジトリを使用することもできます。このため、渡された要求パラメーターに基づいてプロセスを実際に実行するには、おそらく他のオブジェクトをインスタンス化する必要があります。
于 2010-04-23T13:09:38.253 に答える
2

UML の 2 つの設計を比較する場合、UML の 2 番目の API には次のような欠点があります。

  • 呼び出し元は、getDAO() の呼び出しで明示的に DAO のタイプを指定する必要があります。代わりに、呼び出し元は、DAO がインターフェイスに準拠している限り、動作する DAO のタイプを気にする必要はありません。最初の設計では、呼び出し元は単に createDAO() を呼び出して、操作するインターフェイスを取得できます。このようにして、使用する impl の制御がより柔軟になり、呼び出し元がこの責任を負わないため、設計の全体的な一貫性が向上します。
于 2010-04-23T12:43:10.273 に答える
0

抽象ファクトリは、何かを作成する際に選択の複数の次元を分離する必要がある場合に役立ちます。

ウィンドウ システムの一般的な例では、さまざまなウィンドウ システム用のウィジェットのファミリを作成し、そのシステムで動作するウィジェットを作成するウィンドウ システムごとに具体的なファクトリを作成します。

DAO を構築する場合、ドメイン内のさまざまなエンティティに対して DAO のファミリを作成する必要があり、ファミリ全体の「sql」バージョンと「アクセス」バージョンを作成する必要がある場合に便利です。これがあなたの同級生が言おうとしている点だと思います。あなたがそうしているのであれば、それは良い考えであると思われます。

変化するものが 1 つだけある場合、それはやり過ぎです。

于 2010-04-23T21:35:31.137 に答える