2012-07-27 94 views
11

我查了很多關於DAO模式的信息,我明白了這一點。但我覺得大多數解釋並不能說明整個故事,因此我的意思是你會在哪裏使用你的DAO。因此,舉例來說,如果我有一個User類和相應的UserDAO,它能夠保存和恢復用戶對我來說,這是正確的做法:DAO模式和模型對象

  • 控制器創建用戶對象,並把它傳遞給UserDAO的到它保存到數據庫

  • 控制器創建用戶對象,並在其構造用戶對象進行到userDAO的調用,以自身保存到數據庫中

  • 這是一個代碼味道,你是缺少控制器要求創建用戶的額外類「UserManager」。該的UserManager負責創建用戶和要求的UserDAO將其保存

我覺得自己是第三個選擇是最好的,因爲所有的控制器負責的委託請求到正確的模型對象。 你最喜歡的方式是什麼?我在這裏錯過了什麼嗎?

回答

12

我與DAO的經驗,第一種方法是唯一正確的。其原因是,它具有清晰的職責和產生最小雜波(當然,一些非常尊敬的程序員認爲的DAO自己是混亂。亞當邊看到在EntityManager和進一步的DAO已經實施的原DAO模式大部分是不必要的「管道」)

方法2將模型綁定到DAO,從而創建「上游依賴」。我的意思是通常這些模型是作爲單獨的軟件包分發的,並且(並且應該)不知道它們的持久性細節。你所描述的類似模式是Active Record pattern。它在Ruby on Rails中被廣泛使用,但在Java中並未實現同等的優雅和簡單性。

方法3 - 什麼應該是UserManager的點?在你的例子中,管理器執行2個任務 - 它具有用戶工廠的職責,並且是持久性請求的代理。如果它是一個工廠,並且你需要一個,那麼你應該將它命名爲UserFactory而不需要在其上施加額外的任務。至於代理 - 爲什麼你需要它?命名爲...Manager

恕我直言,大多數類有異味。這個名字本身就表明這個班級沒有明確的目的。每當我有一個衝動想要命名一個類...Manager,這是一個信號讓我找到一個更合適的名字或認真思考我的架構。

+1

只是添加到這個;我通常也創建一個負責管理會話/事務的UserServices對象。然後我有UserDAO,它只負責實際執行從UserServices調用的查詢。 – sbrattla 2012-07-27 13:33:44

+0

@sbrattla - 如果你正在使用用戶交易,這肯定是有意義的。我自動承擔了EJB交易,儘管OP沒有提及它們。 Kneejerk :) – kostja 2012-07-27 13:52:12

+0

@Tom如果你不同意 - 請詳細說明 – kostja 2012-07-30 14:11:12

0

數據訪問對象(DAO),應使用更靠近應用程序的數據訪問層。數據訪問對象實際上執行數據訪問活動。所以它是數據訪問層的一部分。

DAO之前的體系結構層可能因項目而異。

控制器基本上用於控制請求流。所以他們有點接近UI。 雖然Manager,Handler是一個壞主意,但我們仍然可以在控制器和DAO之間添加一個圖層。因此,控制器將預處理來自請求或出去的數據(數據完整性,安全性,本地化,國際化,轉換爲JSON等)。它以域對象(在這種情況下爲用戶)的形式向服務發送數據。該服務將調用該用戶的一些業務邏輯或將其用於某些業務邏輯。然後它會傳遞給DAO。

具有控制層的業務邏輯並不好,如果你支持多個客戶端,例如JSP中,Web服務,手持設備等

0

假設控制器是指「C」在MVC,你的第三個選項是正確的做法。一般來說,Controller代碼擴展或遵循框架的約定。 MVC的理想之一是交換框架,這真的是控制器,應該相對容易。控制器應該在模型和視圖層之間來回移動數據。

從模型的角度來看,控制器應該與位於domain model前面的service layer - a contextual boundary進行交互。 UserManager對象將是您將考慮作爲服務層的一部分的一個示例 - 這是域模型的公共API。

0

對於第一種方法;恕我直言,控制器調用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() 
    } 

    } 

}