簡體   English   中英

MVC和存儲庫模式:控制器,模型和存儲庫的角色?

[英]MVC and the Repository Pattern: Roles of Controllers, Models, and Repositories?

所以我一直在研究存儲庫模式的作用,作為在MVC框架中將持久層與我的模型分離的一種方法。 在此之前,我可能會讓我的UserModel直接調用活動記錄方法,以便存儲/檢索域對象。

這是我正在思考的關於應該創建新User的請求中的調用堆棧的草圖:

在此輸入圖像描述

這是我的問題:

  1. 這是存儲庫模式的正確實現嗎?
  2. 我知道控制器應該從請求中獲取用戶的信息並將其傳遞給模型。 這通常是怎么發生的? 控制器應該創建一個User對象,然后將其傳遞給模型嗎? 我確定不想只是將一組值傳遞到模型中 - 我也不想將15個參數傳遞給創建用戶的模型方法。
  3. 為了使這個模式真正起作用,我覺得我需要有一個域對象,它只是一個沒有行為的簡單數據結構,然后如果我使用ORM,我會有一個ORM對象,它將描述對象是如何持久化的。 最初我拒絕這一點,因為它感覺像是重復的代碼,但如果我真的將持久性與業務邏輯分開,那么這需要嗎? 例如,如果我使用內存存儲怎么辦? 我不再使用ORM對象了。

我在這里想得對嗎? 這是可以接受的。 請幫助我連接我的腦袋。

1.這是存儲庫模式的正確實現嗎?

我不確定你在做什么研究,但你弄錯了。

  • 用於將域對象數據映射器分離的存儲庫

  • 沒有“模特”這樣的東西。 MVC設計模式中的模型是主要層之一: 表示層模型層

  • 存儲庫模式與活動記錄 (反)模式不兼容,后者在單個實例中組合了域和存儲邏輯,從而導致嚴重的SRP違規。

要使用真實世界的示例,在何時以及如何使用存儲庫,這是一個示例:

您正在創建一些文檔管理工具,其中所述文檔可以來自多個來源(例如:本地SQL數據庫,SOAP服務和緩存)。 在這種情況下,您將創建一個存儲庫,用於處理存儲的“路由”。 應用程序的一部分決定了用於存儲/檢索每個文檔的數據映射器。

存儲庫的目標是將域邏輯與存儲交互分開。 對於上面描述的系統,存儲庫還可以添加新的數據源,而無需重寫大量代碼(如果有的話)。 您可以為文檔添加另一種類型的映射器。

2.控制器是否應該創建一個User對象然后將其傳遞給模型?

首先,控制器本身不應該創建任何東西。 相反,您的控制器應該使用工廠來獲取您需要的對象的實例。 可以通過構造函數或其他方法將此工廠提供給控制器。 這稱為: 依賴注入 (了解更多信息, 觀看本講座 )。

此外,如上所述,模型是一個層,而不是任何特定的類或對象。 控制器的職責是改變模型層的狀態(通過將數據傳遞給它)。 您可以直接在控制器中與域對象和映射器(或存儲庫)進行交互,但這意味着泄漏控制器中的某些業務邏輯。 建議改為使用服務 ,然后操作所述域對象和存儲相關結構。

至於10+參數的問題,你需要創建新的用戶帳戶,讓我們假設你有以下足跡的行動:

public function postUser( Request $request )
{
    ....
}

如果使用特定的Request實例調用該操作,則有兩個選項可以處理大量參數:

  1. 將實例包裝在裝飾器中 ,這將允許您調用單個方法,以便在特定數組中根據請求形成數據。 然后將此數組傳遞給服務。

  2. 在控制器的動作內部形成數組並傳遞它,需要數據。

前一種解決方案更適用於大規模應用,在這種應用中,除了代碼之外,還需要重復進行這種數據的形成。 但在小型/中型項目中,第二種選擇是常識性方法。

事實上,控制器的工作是獲取用戶的輸入,並將其分配給模型層和當前視圖。 這種陣列的形成符合這一要求。

3.(..)主要對象只是一個沒有行為的簡單數據結構然后(..)

不。域對象不是“簡單數據”。 它是大多數域業務邏輯駐留在應用程序中的位置。

忘了神奇的ORM。 實現存儲庫的第一步是分離域和存儲邏輯。 域對象處理驗證和業務規則,映射器處理持久性和數據完整性( 這里的小例子)。

您必須意識到的另一件事是Web應用程序的存儲庫並不真正與內存持久性(除了緩存)交互。 相反,您的存儲庫將為不同的數據源處理mappers。

控制器應該創建一個User對象,然后將其傳遞給模型嗎?

我不確定你的意思是“將其傳遞模型中” - User對象模型。 “Controller”和“model”代表設計中的不同層,它們不是特定的對象,並且不應該像您提到的那樣單獨的UserModel對象。

存儲庫接口本身通常被認為是模型的一部分,盡管域對象不應該自己保存 - 這應該在控制器中完成。

然后,您的控制器的工作是解釋請求並創建User對象,然后使用存儲庫來保存用戶:

$user = new User(...); // based on Request
$repository->save($user);

它看起來像我,我需要一個域對象,它只是一個沒有行為的簡單數據結構

事實並非如此,您可以並且應該在您的域對象中封裝行為。 至於如何實際執行持久性,一個好的ORM應該處理大部分細節,你不必手動創建其他類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM