如何设计DAO类?

时间:2011-08-29 15:14:14

标签: java

设计DAO课程的最佳方法是什么?

方法#1: 将DAO类设计为对象

class Customer {
//customer class
}

class CustomerDAO {
  public void saveCustomer(Customer customer) {
  //code
  }

  public Customer getCustomer(int id) {
  //code
  }
}

//Client code
class client {
  public static void main(String[] args) {

   CustomerDAO customerDAO = new CustomerDAO();
   Customer customer = new Customer();
   customerDAO.saveCustomer(customer);
  }
}

方法#2: 使用静态方法设计DAO类(又名静态类)

class Customer {
//customer class
}

class CustomerDAO {
  public static void saveCustomer(Customer customer) {
  //code
  }

  public static Customer getCustomer(int id) {
  //code
  }
}

//Client code
class client {
  public static void main(String[] args) {

   Customer customer = new Customer();
   CustomerDAO.saveCustomer(customer);
  }
}

在方法#1中,我必须在所有客户端代码中创建DAO类的对象(其他选项是传递DAO的引用)。在方法#2中,我不必创建对象,静态方法可以设计为没有状态跟踪。

那么哪种方法最适合DAO类的设计?

5 个答案:

答案 0 :(得分:37)

我建议使用方法#1,但是会使用Spring进行依赖注入,而不是直接实例化DAO。

这样,对于单元测试客户端代码,您可以替换模拟DAO,并验证是否使用适当的参数调用了正确的DAO。 (Mockito在这里很有用。)

如果使用静态方法,则单元测试要困难得多,因为无法覆盖静态方法。

答案 1 :(得分:11)

要有更多的抽象:

interface IDAO<T> {

  public save(T t);
  public T getById(int id);
  //...etc

}

然后

public CustomerDao implements IDAO<Customer>{
   public save(Customer c){
        //Code here
    }
   public Customer getById(int id){
      //Code here
    }
}

和DAO到另一个域

public UniversityDao implements IDAO<University>{

     public save(University u){
       //Code here
      }
     public University getById(int id){
        //Code here
     }
}

现在表示层或主类将包含如下代码:

IDAO  dao;
dao=new CustomerDao();
//...
dao=new UniversityDao();

答案 2 :(得分:6)

我也会选择选项1,但我也建议你编程接口。创建一个界面,设置DAO必须提供的功能,然后根据需要实现不同类的功能。

public interface CustomerDao {
    public void saveCustomer(Customer customer);

    public Customer getCustomer(int id);
}

然后你可以拥有class SimpleCustomerDao implements CustomerDAO {/*code here*/}

main(以及您需要的其他任何地方),您将拥有:

//Note that you have an interface variable and a real class object 
CustomerDao customerDao = new SimpleCustomerDao();

你可以弄清楚这样做的好处!

是的,如果您使用SpringGuice,请使用依赖注入!

答案 3 :(得分:5)

请参阅文章如何编写通用DAO(使用Spring AOP): Don't repeat the DAO!

您可以找到技术堆栈的通用DAO实现示例(只是谷歌“不要重复DAO my_technology”)。

答案 4 :(得分:0)

我更喜欢分层方法,这种方法简单告诉我们的是:

  1. 您的模型类为Customer
  2. 您正通过Interface CustomerDAO与客户签订合同

    public interface CustomerDAO{
    
        public void saveCustomer(Customer customer);
        public Customer getCustomer(int id);
    }
    
  3. 您正在拥有像CustomerDAOImpl

    这样的具体实施
    public class CustomerDAOImpl extends CustomerDAO{
    
        public void saveCustomer(Customer customer){
          saveCustomer(customer);
        }
    
        public Customer getCustomer(int id){
          return fetchCustomer(id);
        }
    }
    
  4. 然后编写管理器来管理这些或封装其他一些DAO,如:

    public class ManagerImpl extends Manager{
        CustomerDAO customerDAOObj;
    
        // maybe you need to collect
        // all the customer related activities here in manger
        // because Client must not bother about those things.
    
        UserBillingDAO userBillingDAOObj; 
    
        public void saveCustomer(Customer customer){
          customerDAOObj.saveCustomer(customer);
        }
    
        public Customer getCustomer(int id){
          return customerDAOObj.fetchCustomer(id);
        }
    
        // Note this extra method which is defined in 
        //UserBillingDAO which I have not shown, but you are exposing 
        //this method to your Client or the Presentation layer.
    
         public boolean doBillingOFCustomer(id) {
            return userBillingDAOObj.doBilling(id);
        }
    }
    

    现在表示层或主类将包含如下代码:

    public static void main(String... ar){
         Manager manager = new ManagerImpl();
         manager.saveCustomer();
        // or manager.doBillingOfCustomer(); // etc
    }