19

我查阅了很多关于 DAO 模式的信息,我明白了这一点。但我觉得大多数解释并没有说明全部故事,我的意思是你会在哪里实际使用你的 DAO。因此,例如,如果我有一个 User 类和一个相应的 UserDAO 可以为我保存和恢复用户,这是正确的方法:

  • 控制器创建 User 对象并将其传递给 UserDAO 以将其保存到数据库中

  • 控制器创建用户对象并在其构造函数中用户对象调用 userDAO 以便将自身保存到数据库中

  • 这是一种代码异味,您缺少一个额外的类“UserManager”,控制器将要求该类创建用户。UserManager 负责创建用户并要求 UserDAO 保存

我真的觉得第三种选择是最好的,因为控制器所负责的只是将请求委托给正确的模型对象。你最喜欢的方式是什么?我在这里错过了什么吗?

4

5 回答 5

19

根据我对 DAO 的经验,第一种方法是唯一正确的方法。原因是它的职责最明确,产生的混乱最少(嗯,一些非常受人尊敬的程序员认为 DAO 本身就是混乱的。Adam Bien 认为原始 DAO 模式已经在未来的EntityManagerDAO 中实现,并且更多的 DAO 大多是不必要的“管道”)

方法 2将模型绑定到 DAO,创建“上游依赖项”。我的意思是,通常模型作为单独的包分发,并且(并且应该)不知道它们持久性的细节。与您描述的类似模式是Active Record 模式。它在 Ruby on Rails 中被广泛使用,但在 Java 中并没有以同样优雅和简单的方式实现。

方法3 - 应该是什么UserManager?在您的示例中,管理器执行 2 个任务 - 它具有用户工厂的职责,并且是持久性请求的代理。如果它是一个工厂并且你需要它,你应该命名它UserFactory而不对其施加额外的任务。至于代理 - 为什么需要它?

恕我直言,大多数命名的课程...Manager都有气味。该名称本身表明该类没有明确的目的。每当我有为一个类命名的冲动时...Manager,这都是我找到一个更合适的名称或认真思考我的架构的信号。

于 2012-07-27T13:30:14.497 回答
1

对于第一种方法;恕我直言,在 DAO 对象上调用方法的控制器不是一个好的设计。控制器必须询问有关业务的“服务”级别对象。这些“服务”如何保存数据不是控制器关心的问题。

对于第二种方法;有时您可能只想创建对象,因此构造函数和持久化任务不能像这样紧密耦合。

最后,管理器或服务对象是分层架构的一个很好的抽象。这样,您可以将业务流分组到适当的类和方法中。

但是对于 Play,案例类的伴生对象也是用作 DAO 的良好候选对象。这些对象的单例性质使其成为一个很好的候选对象。

case class TicketResponse(appId: String, ticket: String, ts: String)

object TicketResponse{
  implicit val ticketWrites = Json.writes[TicketResponse]

  def save(response: TicketResponse) = {

    val result = DB.withConnection {
      implicit connection =>

        SQL("insert into tickets(ticket, appid, ts)"
          +   " values ({ticket},{appid},{ts})")
          .on('ticket -> response.ticket, 'appid -> response.appId, 'ts -> response.ts).executeInsert()
    }

  }

}
于 2014-07-31T13:06:46.257 回答
0

数据访问对象 (DAO) 应该更靠近应用程序的数据访问层使用。数据访问对象实际上执行数据访问活动。所以它是数据访问层的一部分。

DAO 之前的架构层可能因项目而异。

控制器基本上用于控制请求流。所以它们有点接近 UI。虽然 Manager 和 Handler 是个坏主意,但我们仍然可以在控制器和 DAO 之间添加一层。因此控制器将预处理来自请求或发出的数据(数据完整性、安全性、本地化、i18n、转换为 JSON 等)。它以域对象(在本例中为用户)的形式向服务发送数据。该服务将调用该用户的某些业务逻辑或将其用于某些业务逻辑。然后它将它传递给 DAO。

如果您支持多个客户端,如 JSP、WebServices、手持设备等,那么在控制器层中拥有业务逻辑并不好。

于 2012-07-27T14:34:38.160 回答
0

假设 Controller 表示MVC中的“C” ,那么您的第三个选项是正确的方法。一般来说,控制器代码扩展或遵循框架的约定。MVC 的理想之一是交换框架,这实际上是 Controller,应该相对容易。控制器应该只是在模型层和视图层之间来回移动数据。

从模型的角度来看,控制器应该与位于域模型前面的服务层上下文边界)进行交互。该对象将是您认为属于您的服务层的一部分的示例——即域模型的公共 API。UserManager

于 2012-07-27T14:46:39.037 回答
-2

对于典型的 webapp,我更喜欢带有 play 的 JPA 和数据库实现的play框架。它更有成效的方式。

请看这里http://www.playframework.org/documentation/1.2.5/jpa 和这里 http://www.playframework.org/documentation/1.2.5/guide1http://www.playframework。 org/documentation/1.2.5/guide2

就是这样))

于 2012-07-27T13:29:53.977 回答