在我的职业生涯中,我看到了几个不同的设计,如何使用DAO,服务,控制器层。我想问一下两个相似但差别不大的两个。 第一种设计在层之间产生可见屏障。控制器始终使用服务而仅使用服务。服务可以使用其他服务或DAO。 控制器不能直接使用任何DAO。这个设计很清楚,但对我来说有很大的不足:我们总是要为DAO中的每个方法创建服务方法。 但在很多情况下,Service方法只调用DAO方法和其他任何东西。
例如:
我们有UserDao
class UserDao {
public List<User> findByName(String name) { ... }
public List<User> findByLastName(String name) { ... }
public List<User> findOlderThan(int age) { ... }
......
}
控制器使用上述所有方法。在我们的案例中我们应该做些什么?在UserService
中创建类似的方法:
class UserService {
public List<User> findByName(String name) { return userDao.findByName(name); }
public List<User> findByLastName(String name) { return userDao.findByLastName(name); }
public List<User> findOlderThan(int age) { return userDao.findOlderThan(age); }
......
}
对我来说,这是只读方法的额外不必要的层。
在第二种设计中,我们没有遇到任何问题,因为我们可以直接在控制器中使用DAO。 在这个设计中我们有一个规则:如果我们想从“数据存储”中检索数据,我们可以在任何层使用DAO,如果我们想在“数据存储”中进行一些更改,我们必须使用服务方法。
关于这些设计,你觉得怎么样?哪个更好?我应该在我的项目中使用哪些应该被遗忘?你能和我分享你在这方面的经验吗?
答案 0 :(得分:3)
服务,MVC和MVC启发的设计模式是模型层的“顶部”。这是表示层与域业务逻辑交互的方式(实际上,“读取”部分应该由视图实例完成)。
在这种结构中,服务充当障碍,隔离表示层,为您以后更改模型内部结构提供额外的自由。
您必须记住的另一件事是,有更多的结构,只有服务与之交互的DAO。首先,有domain objects(业务对象,模型对象),它们封装了与一个特定实体相关的不同业务规则。然后你也可以拥有data mappers,它抽象存储逻辑而不是DAO。或者在映射器和域对象之间转换信息的DAO。在更大规模的应用程序中也可能有unit(s) of work。在较小的范围内,您可以使用一些active record实例。
你可以说模型层包含三个主要的结构组,其中实现了模型的各个方面:域,存储和应用程序逻辑。
应用程序逻辑是存储结构域对象之间的交互。这就是服务的责任。
如果您公开DAO,您的模型层会在演示文稿中启动泄漏。控制器应该不知道使用什么结构,以及它们何时被保留。