5

次のようなコードがあります。

public interface BaseDAO{
// marker interface
}

public interface CustomerDAO extends BaseDAO{
public void createCustomer();
public void deleteCustomer();
public Customer getCustomer(int id);
// etc
}

public abstract class DAOFactory {
public BaseDAO getCustomerDAO();
public static DAOFactory getInstance(){
  if(system.getProperty("allowtest").equals("yes")) {
  return new TestDAOFactory();
  }
  else return new ProdDAOFactory();
}

public class TestDAOFactory extends DAOFactory{
public BaseDAO getCustomerDAO() {
  return new TestCustomerDAO(); // this is a concrete implementation
  //that extends CustomerDAO
  //and this implementation has dummy code on methods
}

public class ProdDAOFactory extends DAOFactory {
public BaseDAO getCustomerDAO() {
  return new ProdCustomerDAO(); // this implementation would have 
  // code that would connect to the database and do some stuff..
}
}

さて、私はこのコードがにおいがすることを知っています..多くの理由があります。ただし、このコードもここにあります: http://java.sun.com/blueprints/corej2eeppatterns/Patterns/DataAccessObject.html、9.8 を参照

私がやろうとしているのはこれです:1)環境(システムプロパティ)に基づいて実行時にDAOの実装を切り替えます。2) 型キャストを回避できるように、Java ジェネリックを使用します...たとえば、次のようなことを行います。

CustomerDAO dao = factory.getCustomerDAO();
dao.getCustomer();

とは対照的に:

CustomerDAO dao = (CustomerDAO) factory.getCustomerDAO();
dao.getCustomer();

あなたの考えや提案をお願いします。

4

4 に答える 4

10

次のようにファクトリを定義する必要があります。

public abstract class DAOFactory<DAO extends BaseDAO> {
public DAO getCustomerDAO();
public static <DAO extends BaseDAO> DAOFactory<DAO> getInstance(Class<DAO> typeToken){
  // instantiate the the proper factory by using the typeToken.
  if(system.getProperty("allowtest").equals("yes")) {
  return new TestDAOFactory();
  }
  else return new ProdDAOFactory();
}

getInstance は、適切に型指定された DAOFactory を返す必要があります。

ファクトリ変数の型は次のとおりです。

DAOFactory<CustomerDAO> factory = DAOFactory<CustomerDAO>.getInstance(CustomerDAO.class);

使用法は適切に入力されます。

CustomerDAO dao = factory.getCustomerDAO();
dao.getCustomer();

唯一の問題は、おそらく getInstance メソッド内で必要なキャストです。

于 2009-05-13T18:48:36.387 に答える
6

必要なものについて詳しく説明した記事がたくさんあります。

DAOFactoryあなたの例とは異なり、 のメソッドが実際のサブクラス (つまり ) を返してはならない理由はないことに注意してくださいCustomerDAO getCustomerDAO()load()/get()/find()さらに、ジェネリック DAO を使用する主な利点は、エンティティ タイプが「ジェネリック化」されていることです。したがって、fromや同様のメソッドをキャストする必要はありません。

于 2009-05-12T23:21:26.887 に答える
5

Your example doesn't demonstrate a need for BaseDAO, and there is no reason why DAOFactory.getCustomerDAO() shouldn't be declared to return a CustomerDAO. So, I don't really see a need for generics there. However, consider the following:

interface DataAccess<T> {
  void store(T entity);
  T lookup(Serialiable identifier);
  void delete(Serializable identifier);
  Collection<? extends T> find(Criteria query);
}

abstract class DataAccessFactory {
  abstract DataAccess<T> getDataAccess(Class<T> clz);
  static DataAccessFactory getInstance() {
    ...
  }
}

私はいくつかのプロジェクトでこのようなアプローチを使用してきましたが、モデル内のすべてのエンティティに対して機能する 1 つの DAO を作成することは非常に優れています。弱点は「ファインダー」メソッドです。きちんとしたアプローチがいくつかあり、JPA での今後の作業は「基準」API の標準化ですが、今のところ、基礎となる永続メカニズムの基準を公開するのが最も簡単な場合がよくあります。

于 2009-05-12T23:24:05.870 に答える
0

ファクトリを使用したときは、通常は instanceof を使用してオブジェクトの真の型を判断しました。例えば:

CustomerDAO dao;
if (factory.getCustomerDAO() instanceof CustomerDAO) {
   dao = factory.getCustomerDAO();
}
dao.getCustomer();

これは、特に factory.getCustomerDAO() が CustomerDAO に近いものを返さない場合 (実装の変更により)、私にとってはすっきりしているように思えます。

ちょうど私の2セント。

于 2009-05-12T23:20:14.207 に答える