三層架構(DAL/BLL/UI)和MVC設計模式的關系


首先,MVC和三層架構,是不一樣的。


BLL   是業務邏輯層   Business   Logic   Layer   

DAL   是數據訪問層   Data   Access   Layer          

ASP.NET的三層架構(DAL,BLL,UI)

 圖形表示三層結構. 其中web即為USL層

web –> bll –> dal
|           |          |
|           V          |
+–> model <—+


  三層架構中,DAL(數據訪問層)、BLL(業務邏輯層)、WEB層各司其職,意在職責分離。
  MVC是 Model-View-Controller,嚴格說這三個加起來以后才是三層架構中的WEB層,也就是說,MVC把三層架構中的WEB層再度進行了分化,分成了控制器、視圖、實體三個部分,控制器完成頁面邏輯,通過實體來與界面層完成通話;而C層直接與三層中的BLL進行對話。
  所以, .net的三層結構中,並沒有action這個概念。
  asp.net mvc 是微軟新發布的一種網站開發架構。為了解決傳統asp.net開發中不能分離Model,View和Controller而設計的。
  普通的網站為了解決可移植,可維護,可擴展等問題,會把網站設計成三個獨立的模塊,Model負責數據庫部分,View負責網頁的界面,而Controller負責界面與數據的交互及業務邏輯,這樣設計的網站如果想設計或者重新開發某一個模塊對其他的模塊是沒有影響的。但是asp.net的頁面后台代碼與每個頁面代碼都是一一對應的,業務邏輯在某些情況下不可避免的被寫到了與View關聯的后台代碼中。這樣就不能保證View與Controller的分離,也就很難實現網站的重寫和升級。
  而在MVC中頁面代碼並不是與后台代碼一一對應,而是分別被存放成Controller和View兩個部分,徹底的解決了,View和Controller不能獨立的問題。從而改善網站的重寫和升級過程。
  但是MVC也有其缺點,由於在頁面代碼中不再可以使用服務器控件,因此給某些asp.net服務器端控件的使用帶來了麻煩,而且MVC也頁面的設計工作帶來了很多障礙。
  ASP.NET MVC 是微軟在2009年4月份發布的一種新的網站開發架構,http://msdn.microsoft.com/en-us/library/dd394709.a spx,它是把傳統意義上的MVC開發思想融合到了ASP.NET的開發當中。
  那么我也來講講我對這兩者的理解吧。
  首先對這個題目,本身是存在問題的,"XX結構"與"XX模式"的區別?請問中國社會制度與美國人生活方式有什么區別?
  這兩者本身講的是不同方向與角度的問題,在實際應用中他們的確存在一些相似的特點,在很多書籍中也沒有深入講解,以致於造成困惑,為了更好的理解他們,姑且來說說區別吧。
  首先N層結構是一種軟件抽象的層次結構,是對復雜軟件的一種縱向切分,每一層次中完成同一類型的操作,以便將各種代碼以其完成的使命作為依據來分割,以將低軟件的復雜度,提高其可維護性。一般來說,層次之間是向下依賴的,下層代碼未確定其接口(契約)前,上層代碼是無法開發的,下層代碼接口(契約)的變化將使上層的代碼一起變化。三層結構是N層結構的一種,是人產在長時間使用中得出來的一種應用場合廣泛的N層結構,被當作一種典型的軟件層次結構而廣為流傳甚至寫入教科書。
  MVC模式是一種復合設計模式,一種在特定場合用於解決某種實際問題來得出的可以反復實踐的解決方案。巧合的是他也有三個事物組成,於是乎人們就有了一種想當然的對應關系:展示層-View;業務邏輯層-Control;持久層-Model。首先MVC中的三個事物之間並不存在明顯的層次結構,沒有明顯的向下依賴關系,相反的,View和Model往往是比較獨立的,而Control是連接兩者的橋梁,他們更像是橫向的切分。這樣一來就出現一個結果,MVC中每個塊都是可以獨立測試的,而三層結構中,上層模塊的運行測試勢必要提供下層代碼或者提供相同接口的樁。相對來說,MVC復雜得多,但是結構更清晰,耦合性更低。
  另外,MVC中每一塊內部特別是Model內部經常被設計為多層的。在我認為的一個良好的MVC模式構建的結構中,Control是核心,小且較為穩定的,可以作為一個核心框架來提供,有擴展點,但基本上可以簡單配置不需要任何代碼就可以運行。而View則可能是一套或多種可選擇的視圖引擎,決定了軟件展示給用於的界面,使用時的主要工作量在於擴展點以及根據需要而數量不同的視圖模板。Model則是業務提供者,決定了軟件提供的功能,其內部可能是一些普通的類或者是實現了某些接口的類,在這一塊當中可能根據業務的不同而色彩繽紛,對於復雜的軟件可能會分成很多層,如業務邏輯層、業務提供層、系統提供層、數據提供層、數據訪問層等。
  我經常用於比喻MVC的例子是小時候玩的那種卡帶式游戲機,Control是主機,一般來說我買一個主機就行了,只要他不壞,他就能一直讓我玩這一類的游戲。View則是電視機和游戲手柄,電視機可以獨立工作,他不管輸入的是電視信號、影碟機信號還是游戲機信號,他只管顯示,而且他決定了我們看到的效果是怎么樣的,如果我想要個尺寸更大的或者彩色的顯示效果,我只需要買個相應的電視機就行了,手柄也是可以換的,要遙桿還是帶震動的。Model則是游戲卡帶,他絕定了我玩的是什么游戲,是魂斗羅還是超級瑪莉,而且游戲機主機和電視機生產廠家永遠也不知道在上面有可能會運行什么樣的游戲。卡帶中可能會有游戲代碼和存儲單元,都根據游戲的需要而設計。
  有朋友提到游戲主機提供的卡帶插槽的接口,在設計中,有時也由Control提供一組接口,以用於Model或View的實現,這樣就形成了依賴。一般來說這樣設計也沒有太大的問題,只是會提高模塊間的耦合度,也會帶來一些侵入性。為了更完美,可以不用接口來提供契約,可以用配置信息(或稱元數據信息)+反射來提供契約,那么這個類接口就可以退化到只要符合CLS就可以了,也就是普通的類,就像現在的計算機接口廣泛采用USB,無論是U盤、打印機、掃描儀或者是加密狗,他們都是普通的USB設備而已。
  提到USB有一個題外話,模塊的可插拔性設計甚至是熱插拔設計,系統可以在不停止運行的情況下動態的掛載或移除模塊,動態掛載模塊需要系統能夠自動發現新模塊並根據自描述的信息進行自動配置,移除可能情況更復雜一點,需要"安全刪除硬件"類似的功能。
  在設計廣泛重用的框架時會考慮多種情況以達到更大的適應性,一般項目中應用MVC模式可以較為隨意。

所以呢,你可以完全不用ORM那套東西,直接用代碼生成器,生成三層架構,把WEB層換成mvc模式的,like this:

 

 

 

三層架構的有關問題~~~~


一、三層體系架構
  1.表示層(USL):主要表示WEB方式,也可以表示成WINFORM方式。如果邏輯層相當強大和完善,無論表現層如何定義和更改,邏輯層都能完善地提供服務。
  2.業務邏輯層(BLL):主要是針對具體的問題的操作,也可以理解成對數據層的操作,對數據業務邏輯處理。如果說數據層是積木,那邏輯層就是對這些積木的搭建。
  3.數據訪問層(DAL):主要是對原始數據(數據庫或者文本文件等存放數據的形式)的操作層,而不是指原始數據,也就是說,是對數據的操作,而不是數據庫,具體為業務邏輯層或表示層    

        提供數據服務.

二、具體區分
  1.表示層:主要對用戶的請求接受,以及數據的返回,為客戶端提供應用程序的訪問。
  2.業務邏輯層:主要負責對數據層的操作,也就是說把一些數據層的操作進行組合。
  3.數據訪問層:主要看你的數據層里面有沒有包含邏輯處理,實際上他的各個函數主要完成各個對數據文件的操作,而不必管其他操作。

三、總結
  三層結構是一種嚴格分層方法,即數據訪問層(DAL)只能被業務邏輯層(BLL)訪問,業務邏輯層只能被表示層(USL)訪問,用戶通過表示層將請求傳送給業務邏輯層,業務邏輯層完成相關業務規則和邏輯,並通過數據訪問層訪問數據庫獲得數據,然后按照相反的順序依次返回將數據顯示在表示層。有的三層結構還加了Factory、Model等其他層,實際都是在這三層基礎上的一種擴展和應用.

一個簡單的三層結構程序一般包括DAL BLL WEB Model幾個項目,它們的相互引用關系如下
1) WEB引用 BLL,Model
2)BLL引用 DAL,Model
3)DAL引用Model
4)Model無引用

 一提三層架構,大家都知道是表現層(UI),業務邏輯層(BLL)和數據訪問層(DAL),而且每層如何細分也都有很多的方法。但具體代碼怎么寫,到底那些文件算在哪一層,卻是模模糊糊的。下面用一個簡單的例子來帶領大家實戰三層架構的項目,這個例子只有一個功能,就是用戶的簡單管理。 

     首先建立一個空白解決方案,添加如下項目及文件 
     1、添加ASP.NET Web Application項目,命名為UI,新建Web Form類型文件User.aspx(含User.aspx.cs) 
     2、添加ClassLibrary項目,命名為BLL,新建Class類型文件UserBLL.cs 
     3、添加ClassLibrary項目,命名為DAL,新建Class類型文件UserDAL.cs。添加SQLHelper引用。(這個是微軟的數據訪問類,也可以不用,直接編寫所有的數據訪問代碼。我一般用自己寫的數據訪問類DataAccessHelper )。 
     4、添加ClassLibrary項目,命名為Model,新建Class類型文件UserModel.cs 
     5、添加ClassLibrary項目,命名為IDAL,新建Interface類型文件IUserDAL.cs 
     6、添加ClassLibrary項目,命名為ClassFactory 
     相信大家已經看出來了,這個和Petshop的示例沒什么區別,而且更簡單,因為在下也是通過Petshop學習三層架構的。但一些朋友對於這幾個項目所處的層次,以及它們之間的關系,可能比較模糊,這里逐個說明一下: 
     1、User.aspx和User.aspx.cs 
     這兩個文件(以及文件所屬的項目,下面也是如此,不再重復強調了)都屬於表現層部分。User.aspx比較好理解,因為它就是顯示頁面了。User.aspx.cs有些人覺得不應該算,而是要划到業務邏輯層中去。如果不做分層的話,那么讓User.aspx.cs來處理業務邏輯,甚至操作數據庫都沒什么問題,但是做分層的話,這樣就不應該了。在分層結構中,User.aspx.cs僅應該處理與顯示有關的內容,其它部分都不應該涉及。 
     舉例:我們實現用列表方式顯示用戶的功能,那么提取信息的工作是由BLL來做的,UI(本例中是User.aspx.cs)調用BLL得到UserInfo后,通過代碼綁定到User.aspx的數據控件上,就實現了列表的顯示。在此過程中User.aspx.cs對UI沒有起到什么作用,僅是用來傳遞數據,而且因為實際編碼中大部分情況都是如此的實現,所以使有些人覺得User.aspx.cs不應該算UI,而應該並入BLL負責邏輯處理。繼續往下看,這時提出了一個新需求,要求在每個用戶的前面加一個圖標,生動地表現出用戶的性別,而且不滿18歲的用兒童圖標表示。這個需求的實現,就輪到User.aspx.cs來做了,這種情況下User.aspx.cs才算有了真正的用途。 
     2、NewBLL.cs 
     添加如下方法: 
     public IList GetUsers():返回所有的用戶信息列表 
     public UserInfo GetUser(int UserId):返回指定用戶的詳細信息 
     public bool AddUser(UserInfo User):新增用戶信息 
     public bool ChangeUser(UserInfo User):更新用戶信息 
     public void RemoveUser(int UserId):移除用戶信息 
     此文件就屬於業務邏輯層了,專門用來處理與業務邏輯有關的操作。可能有很多人覺得這一層唯一的用途,就是把表現層傳過來的數據轉發給數據層。這種情況確實很多,但這只能說明項目比較簡單,或者項目本身與業務的關系結合的不緊密(比如當前比較流行的MIS),所以造成業務層無事可做,只起到了一個轉發的作用。但這不代表業務層可有可無,隨着項目的增大,或者業務關系比較多,業務層就會體現出它的作用來了。 
     此處最可能造成錯誤的,就是把數據操作代碼划在了業務邏輯層,而把數據庫作為了數據訪問層。 
     舉例:有些朋友感覺BLL層意義不大,只是將DAL的數據提上來就轉發給了UI,而未作任何處理。看一下這個例子 
     BLL層 
     SelectUser(UserInfo userInfo)根據傳入的username或email得到用戶詳細信息。 
     IsExist(UserInfo userInfo)判斷指定的username或email是否存在。 
     然后DAL也相應提供方法共BLL調用 
     SelectUser(UserInfo userInfo) 
     IsExist(UserInfo userInfo) 
     這樣BLL確實只起到了一個傳遞的作用。 
     但如果這樣做: 
     BLL.IsExist(Userinfo userinfo) 
     { 
     UerInfo user = DAL.SelectUser(User); 
     return (userInfo.Id != null); 
     } 
     那么DAL就無需實現IsExist()方法了,BLL中也就有了邏輯處理的代碼。 
     3、UserModel.cs 
     實體類,這個東西,大家可能覺得不好分層。包括我以前在內,是這樣理解的:UI?àModel?àBLL?àModel?àDAL,如此則認為Model在各層之間起到了一個數據傳輸的橋梁作用。不過在這里,我們不是把事情想簡單,而是想復雜了。 
     Model是什么?它什么也不是!它在三層架構中是可有可無的。它其實就是面向對象編程中最基本的東西:類。一個桌子是一個類,一條新聞也是一個類,int、string、doublie等也是類,它僅僅是一個類而已。 
     這樣,Model在三層架構中的位置,和int,string等變量的地位就一樣了,沒有其它的目的,僅用於數據的存儲而已,只不過它存儲的是復雜的數據。所以如果你的項目中對象都非常簡單,那么不用Model而直接傳遞多個參數也能做成三層架構。 
     那為什么還要有Model呢,它的好處是什么呢。下面是思考一個問題時想到的,插在這里: 
     Model在各層參數傳遞時到底能起到做大的作用? 
     在各層間傳遞參數時,可以這樣: 
     AddUser(userId,userName,userPassword,…,) 
     也可以這樣: 
     AddUser(userInfo) 
     這兩種方法那個好呢。一目了然,肯定是第二種要好很多。 
     什么時候用普通變量類型(int,string,guid,double)在各層之間傳遞參數,什么使用Model傳遞?下面幾個方法: 
     SelectUser(int UserId) 
     SelectUserByName(string username) 
     SelectUserByName(string username,string password) 
     SelectUserByEmail(string email) 
     SelectUserByEmail(string email,string password) 
     可以概括為: 
     SelectUser(userId) 
     SelectUser(user) 
     這里用user這個Model對象囊括了username,password,email這三個參數的四種組合模式。UserId其實也可以合並到user中,但項目中其它BLL都實現了帶有id參數的接口,所以這里也保留這一項。 
     傳入了userInfo,那如何處理呢,這個就需要按照先后的順序了,有具體代碼決定。 
     這里按這個順序處理 
     首先看是否同時具有username和password,然后看是否同時具有email和password,然后看是否有username,然后看是否有email。依次處理。 
     這樣,如果以后增加一個新內容,會員卡(number),則無需更改接口,只要在DAL的代碼中增加對number的支持就行,然后前台增加會員卡一項內容的表現與處理即可。 
     4、UserDAL.cs 
     public IList SelectUsers():返回所有的用戶信息列表 
     public UserInfo SelectUser(int UserId):返回指定用戶的相信信息 
     public bool InsertUser(UserInfo User):新增用戶信息 
     public bool UpdateUser(UserInfo User):更新用戶信息 
     public void DeleteUser(int UserId):移除用戶信息 
     很多人最鬧不清的就是數據訪問層,到底那部分才算數據訪問層呢?有些認為數據庫就是數據訪問層,這是對定義沒有搞清楚,DAL是數據訪問層而不是數據存儲層,因此數據庫不可能是這一層的。也有的把SQLHelper(或其同類作用的組件)作為數據訪問層,它又是一個可有可無的東西,SQLHelper的作用是減少重復性編碼,提高編碼效率,因此如果我習慣在乎效率或使用一個非數據庫的數據源時,可以丟棄SQLHelper,一個可以隨意棄置的部分,又怎么能成為三層架構中的一層呢。 
     可以這樣定義:與數據源操作有關的代碼,就應該放在數據訪問層中,屬於數據訪問層 
     5、IUserDAL 
     數據訪問層接口,這又是一個可有可無的東西,因為Petshop中帶了它和ClassFactory類工廠,所以有些項目不論需不需要支持多數據源,都把這兩個東西做了進來,有的甚至不建ClassFactory而只建了IDAL,然后“IUserDAL iUserDal = new UserDAL();”,不知意義何在。這就完全是畫虎不成反類犬了。 
     許多人在這里有一個誤解,那就是以為存在這樣的關系:BLL?àIDAL?àDAL,認為IDAL起到了BLL和DAL之間的橋梁作用,BLL是通過IDAL來調用DAL的。但實際是即使你如此編碼:“IUserDAL iUserDal = ClassFacotry.CreateUserDAL();”,那么在執行“iUserDal.SelectUsers()”時,其實還是執行的UserDAL實例,而不是IUserDAL實例,所以IDAL在三層中的位置是與DAL平級的關系。 
     通過上面的介紹,基本上將三層架構的層次結構說明了。其實,本人有一個判斷三層架構是否標准的方法,那就是將三層中的任意一層完全替換,都不會對其它兩層造成影響,這樣的構造基本就符合三層標准了(雖然實現起來比較難^_^)。例如如果將項目從B/S改為C/S(或相反),那么除了UI以外,BLL與DAL都不用改動;或者將SQLServer改為Oracle,只需替換SQLServerDAL到OracleDAL,無需其它操作等等。本來想在文中加入一些具體的代碼的,但感覺不是很必要,如果大家覺得需要的話,我再補充吧。 
     總結:不要因為某個層對你來說沒用,或者實現起來特別簡單,就認為它沒有必要,或者摒棄它,或者挪作它用。只要進行了分層,不管是幾層,每一層都要有明確的目的和功能實現,而不要被實際過程所左右,造成同一類文件位於不同層的情況發生。也不要出現同一層實現了不同的功能的情況發生。


————————————————
版權聲明:本文為CSDN博主「默一鳴」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/yimingsilence/article/details/52911859


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM