本文用一個示例來介紹如何建設一個三層架構的項目並說明項目中各個文件所處的層次與作用寫本文的目的不是為了說明自己的這個方法有多對而是希望給那些初學三層架構卻不知從何入手的朋友提供一點幫助因為網上的文章大多是注重理論的介紹而忽略了具體的實踐應用或者有示例但講得不透徹導致看了之後理論上又學習了一遍但還是不知道代碼怎麼寫所以想從這個方面入手寫一下讓從來沒做過三層架構的初學者也能照貓畫虎寫出代碼來文中的代碼是偽代碼僅用來闡明思路
正文
一提三層架構大家都知道是表現層(UI)業務邏輯層(BLL)和數據訪問層(DAL)而且每層如何細分也都有很多的方法但具體代碼怎麼寫到底那些文件算在哪一層卻是模模糊糊的下面用一個簡單的例子來帶領大家實戰三層架構的項目這個例子只有一個功能就是用戶的簡單管理
首先建立一個空白解決方案添加如下項目及文件
添加ASPNET Web Application項目命名為UI新建Web Form類型文件Useraspx(含Useraspxcs)
添加ClassLibrary項目命名為BLL新建Class類型文件UserBLLcs
添加ClassLibrary項目命名為DAL新建Class類型文件UserDALcs添加SQLHelper引用(這個是微軟的數據訪問類也可以不用直接編寫所有的數據訪問代碼我一般用自己寫的數據訪問類DataAccessHelper )
添加ClassLibrary項目命名為Model新建Class類型文件UserModelcs
添加ClassLibrary項目命名為IDAL新建Interface類型文件IUserDALcs
添加ClassLibrary項目命名為ClassFactory
相信大家已經看出來了這個和Petshop的示例沒什麼區別而且更簡單因為在下也是通過Petshop學習三層架構的但一些朋友對於這幾個項目所處的層次以及它們之間的關系可能比較模糊這裡逐個說明一下
Useraspx和Useraspxcs
這兩個文件(以及文件所屬的項目下面也是如此不再重復強調了)都屬於表現層部分Useraspx比較好理解因為它就是顯示頁面了Useraspxcs有些人覺得不應該算而是要劃到業務邏輯層中去如果不做分層的話那麼讓Useraspxcs來處理業務邏輯甚至操作數據庫都沒什麼問題但是做分層的話這樣就不應該了在分層結構中Useraspxcs僅應該處理與顯示有關的內容其它部分都不應該涉及
舉例我們實現用列表方式顯示用戶的功能那麼提取信息的工作是由BLL來做的UI(本例中是Useraspxcs)調用BLL得到UserInfo後通過代碼綁定到Useraspx的數據控件上就實現了列表的顯示在此過程中Useraspxcs對UI沒有起到什麼作用僅是用來傳遞數據而且因為實際編碼中大部分情況都是如此的實現所以使有些人覺得Useraspxcs不應該算UI而應該並入BLL負責邏輯處理繼續往下看這時提出了一個新需求要求在每個用戶的前面加一個圖標生動地表現出用戶的性別而且不滿歲的用兒童圖標表示這個需求的實現就輪到Useraspxcs來做了這種情況下Useraspxcs才算有了真正的用途
NewBLLcs
添加如下方法
public IList<UserInfo> 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確實只起到了一個傳遞的作用
但如果這樣做
BLLIsExist(Userinfo userinfo)
{
UerInfo user = DALSelectUser(User)
return (userInfoId != null)
}
那麼DAL就無需實現IsExist()方法了BLL中也就有了邏輯處理的代碼
UserModelcs
實體類這個東西大家可能覺得不好分層包括我以前在內是這樣理解的UI?àModel?àBLL?àModel?àDAL如此則認為Model在各層之間起到了一個數據傳輸的橋梁作用不過在這裡我們不是把事情想簡單而是想復雜了
Model是什麼?它什麼也不是!它在三層架構中是可有可無的它其實就是面向對象編程中最基本的東西類一個桌子是一個類一條新聞也是一個類intstringdoublie等也是類它僅僅是一個類而已
這樣Model在三層架構中的位置和intstring等變量的地位就一樣了沒有其它的目的僅用於數據的存儲而已只不過它存儲的是復雜的數據所以如果你的項目中對象都非常簡單那麼不用Model而直接傳遞多個參數也能做成三層架構
那為什麼還要有Model呢它的好處是什麼呢下面是思考一個問題時想到的插在這裡
Model在各層參數傳遞時到底能起到做大的作用?
在各層間傳遞參數時可以這樣
AddUser(userIduserNameuserPassword…)
也可以這樣
AddUser(userInfo)
這兩種方法那個好呢一目了然肯定是第二種要好很多
什麼時候用普通變量類型(intstringguiddouble)在各層之間傳遞參數什麼使用Model傳遞?下面幾個方法
SelectUser(int UserId)
SelectUserByName(string username)
SelectUserByName(string usernamestring password)
SelectUserByEmail(string email)
SelectUserByEmail(string emailstring password)
可以概括為
SelectUser(userId)
SelectUser(user)
這裡用user這個Model對象囊括了usernamepasswordemail這三個參數的四種組合模式UserId其實也可以合並到user中但項目中其它BLL都實現了帶有id參數的接口所以這裡也保留這一項
傳入了userInfo那如何處理呢這個就需要按照先後的順序了有具體代碼決定
這裡按這個順序處理
首先看是否同時具有username和password然後看是否同時具有email和password然後看是否有username然後看是否有email依次處理
這樣如果以後增加一個新內容會員卡(number)則無需更改接口只要在DAL的代碼中增加對number的支持就行然後前台增加會員卡一項內容的表現與處理即可
UserDALcs
public IList<UserInfo> 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一個可以隨意棄置的部分又怎麼能成為三層架構中的一層呢
可以這樣定義與數據源操作有關的代碼就應該放在數據訪問層中屬於數據訪問層
IUserDAL
數據訪問層接口這又是一個可有可無的東西因為Petshop中帶了它和ClassFactory類工廠所以有些項目不論需不需要支持多數據源都把這兩個東西做了進來有的甚至不建ClassFactory而只建了IDAL然後IUserDAL iUserDal = new UserDAL()不知意義何在這就完全是畫虎不成反類犬了
許多人在這裡有一個誤解那就是以為存在這樣的關系BLL?àIDAL?àDAL認為IDAL起到了BLL和DAL之間的橋梁作用BLL是通過IDAL來調用DAL的但實際是即使你如此編碼IUserDAL iUserDal = ClassFacotryCreateUserDAL()那麼在執行iUserDalSelectUsers()時其實還是執行的UserDAL實例而不是IUserDAL實例所以IDAL在三層中的位置是與DAL平級的關系
通過上面的介紹基本上將三層架構的層次結構說明了其實本人有一個判斷三層架構是否標准的方法那就是將三層中的任意一層完全替換都不會對其它兩層造成影響這樣的構造基本就符合三層標准了(雖然實現起來比較難^_^)例如如果將項目從B/S改為C/S(或相反)那麼除了UI以外BLL與DAL都不用改動或者將SQLServer改為Oracle只需替換SQLServerDAL到OracleDAL無需其它操作等等本來想在文中加入一些具體的代碼的但感覺不是很必要如果大家覺得需要的話我再補充吧
總結不要因為某個層對你來說沒用或者實現起來特別簡單就認為它沒有必要或者摒棄它或者挪作它用只要進行了分層不管是幾層每一層都要有明確的目的和功能實現而不要被實際過程所左右造成同一類文件位於不同層的情況發生也不要出現同一層實現了不同的功能的情況發生
From:http://tw.wingwit.com/Article/program/net/201311/11365.html