Как создать класс DAO?
Каким должен быть лучший способ разработки класса 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 со статическими методами (aka static class)
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?
Ответы
Ответ 1
Я бы рекомендовал подход № 1, но использовал бы Spring для инъекции зависимостей, а не для непосредственного создания DAO.
Таким образом, для модульного тестирования клиентского кода вы можете подменять макеты DAO и проверять, что правильные DAO вызываются с соответствующими аргументами. (Мокито полезен здесь.)
Если вы используете статические методы, то модульное тестирование намного сложнее, поскольку статические методы не могут быть переопределены.
Ответ 2
Чтобы иметь больше абстракции:
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();
Ответ 3
Я бы пошел на вариант 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();
Вы можете понять преимущества этого!
И да, если вы используете Spring или Guice, тогда используйте Injection Dependency!
Ответ 4
Обратитесь к статье, как написать общий DAO (используя Spring AOP):
Не повторяйте DAO!
Вы можете найти примеры общих реализаций DAO для вашего стека технологий (просто Google "Не повторяйте DAO my_technology" ).
Ответ 5
Я бы предпочел, чтобы слоистый подход и что этот подход просто сказал нам:
- У вас есть модельный класс Customer
-
У вас есть контракт с клиентом через интерфейс CustomerDAO
public interface CustomerDAO{
public void saveCustomer(Customer customer);
public Customer getCustomer(int id);
}
-
У вас есть конкретная реализация, например CustomerDAOImpl
public class CustomerDAOImpl extends CustomerDAO{
public void saveCustomer(Customer customer){
saveCustomer(customer);
}
public Customer getCustomer(int id){
return fetchCustomer(id);
}
}
Затем запишите менеджера для управления этими или инкапсулированием некоторых других 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
}