淺談三層架構 收藏
自己理解的原理
http://www.cnblogs.com/mahaisong/archive/2011/05/12/2044665.html
淺談三層架構 通過這個,+Java開發模式經驗。終於相通了,動軟到底是為什麼這麼做。
,NET開發兩個專案了。半年了。一直沒搞懂。為什麼。net的三層是這樣的。原來今天這裡的三層是這樣的啊?
BLL 做業務邏輯。 DAL 做 資料操縱。 第三次是 介面層(codeBehind).
這就是三層。和JAVA沒什麼不同。只不過。我一直在糾結。為什麼 MVC 要這樣分。其實我錯了。MVC 是最基礎,然後再分成三層。為什麼這麼說那。
MVC。M(Model)-V(View)-C(Control)。 我們一般做操作就把COntorl 做成一個操作的封裝就O了。
而如果開闢大局觀的物件導向的話。 Model是資料的物件核心。 而操作的核心 因為 物件導向的 思想。進行各種介面化 (自動選擇對應的資料庫。封裝的概念。) 這樣就把物件導向 超越編碼 提高到了架構上了。
因此。這裡它還增加了一個工廠模式。
我這裡分析一下。 Bll 做業務邏輯。
private readonly IActivityComment dal=DataAccess.CreateActivityComment();
利用 介面
public sealed class DataAccess
{
private static readonly string AssemblyPath = ConfigurationManager.AppSettings["DAL"];
//不使用快取
private static object CreateObjectNoCache(string AssemblyPath, string classNamespace)
{
try
{
object objType = Assembly.Load(AssemblyPath).CreateInstance(classNamespace);
return objType;
}
catch//(System.Exception ex)
{
//string str=ex.Message;// 記錄錯誤日誌
return null;
}
}
//使用快取
/// <summary>
/// 建立ActivityComment資料層介面
/// </summary>
public static database.IDAL.IActivityComment CreateActivityComment()
{
string ClassNamespace = AssemblyPath + ".ActivityComment";
object objType = CreateObject(AssemblyPath, ClassNamespace);
return (database.IDAL.IActivityComment)objType;
}
利用反射,反射到SQLSERVERDAL,得到資料,封裝到介面中。 而Bll中的方法,和IDAL的方法是對應的關係(大多數)。因為為了封裝,就利用BLL中的方法呼叫實際的IDAL中的方法。(反射,委託,事件,在三個的存在+更高層次的物件導向是 真正難理解的地方。)
每天思考深一點三層。終身受益。
三層架構並不是MVC,MVC是一個很早就有的經典的程式設計模式,M-V-C分為三層,M(Model)-V(View)-C(Control)。而web開發中的三層架構是指:資料訪問層(DAL-DatabaseAccessLayer),業務邏輯層(BLL-BusinessLoginLayer),以及使用者介面層(UI-UserInterface,實際就是網頁後臺的具體呼叫BLL層)。這個是基本概念。曾經我以為三層架構就是在AppCode中,分為三個大類與若干小類,各司其職。在經過一番洗禮後,才發覺多麼的無知。
首先AppCode中,放的是通用類,如資料庫通用類,實現資料庫連線,基本的SqlCommand建立,自定義CRUD的方法等,與三層架構毫無關係,就是常用的開發模式中存放類(Class)的資料夾。
其次,當使用三層架構時,一定是在大專案中,因為三層架構的目的是提高專案的鬆散性和降低專案的耦合度,使之更容易擴充套件或者維護。小專案使用了三層架構,由於過度的在意分層而導致了專案的複雜度增加。
建立三層架構的應用程式。我們必須對這三層分別建立不同的類庫(ClassLibrary),而不是普通的類(Class)。我們對於任何一個模組或者功能進行OOP,把它擴充套件為物件(物件導向的思想就是:將所操作的目標當成一個物件,對它進行的操作,將由物件自己的方法進行,而非外界傳參。譬如註冊使用者,用程式導向的方法事先,就是:public static bool Register(string userName, string userPwd)。若用OO的思想,我們不可將賬號密碼作為引數傳入,而是將使用者作為一個物件,這個物件具有private _userName,和private _userPwd的屬性。在註冊時,用建構函式初始化一個新的物件,User one = new User(userName,userPwd),使之在初始化後具有這兩個欄位的值。然後呼叫User類中的public static bool Register()方法(注意這個方法是不進行傳參的),而在這個Register方法中,使用物件的_userName和_userPwd屬性進行註冊。),那麼,我們在這個物件中的任何操作都將以該物件的方法(函式)實現。
在進行三層分類時,這樣新建類庫。
1.檔案->新建專案->其他專案型別->空白解決方案。
2.在右側的“資源管理器”中,選中當前解決方案,右鍵新增->新建專案->類庫(ClassLibrary),分別建立BLL,DAL,UL類庫。(若新增後看不到解決方案則在選單->工具->選項->專案和解決方案->總是顯示解決方案)。
3.右鍵,向解決方案中新增一個網站(新網站或者現有網站)。
4.根據需求刪除或者保留預設新增項(預設的class1.cs或Default.aspx檔案)。
這樣一個三層架構的網站雛形就搭建好了。因為UI層要被其他兩層引用,DAL層要被BLL層引用。所以需要相互新增引用,方法是在類庫上點選右鍵->新增引用->專案->選擇其他類庫。並且在具體類中引入名稱空間(using namespace)。
ps:類庫其實就是類的集合,三層架構的目的就是,將同一專案的不同模組都劃分為各自的三層,各司其職,將具體實現方法用類寫出,新增到該層的類庫中,這樣,一個網站下的類庫就只有三層,每一層中都包含了各個模組相對應層的實現方法。在以後修改或擴充套件時,在對應層中進行操作就可以了。
一般的專案,涉及最多的就是對資料庫的CRUD,DAL層只負責與資料庫的互動,BLL層是最重要的一層,他負責將DAL層的的結果呈現給UI層,但是恰恰BLL層的存在似乎有點雞肋,他起到的僅僅是轉發DAL層資料的作用,而具體的邏輯操作是與資料庫的互動,應該寫在DAL層,這就好像BLL層是在重複DAL層的勞動一樣,其實BLL層的作用在於除了呼叫DAL層訪問資料庫,還可以進行邏輯判斷,當符合的時候,才進行允許進行DAL的操作,或者進行額外的操作(如加密,轉換等)。而DAL層可不管這些,他只管進行CRUD的動作。UI層就是操作抽象出來的實體物件,它包含了各種屬性。
在這裡我說一下。簡單三層的架構:WEB,BLL ,DAL做主框架。而MOdel 因為物件導向+每層都用。所以獨立出來。和DAL並列。
解密,快取,資料校驗,因為是通用,也單獨分離。放在Common類中。而,資料庫訪問類,因為資料庫的多種多樣,所以有一個 通用的資料庫操作類。叫做DBUtility 獨立出來,專門做 資料庫訪問的,(例如,反射後自動區分是訪問EXCEL還是SQL),與Common並列。
DBUtility是對ADO.NET的封裝,封裝了一些常用的重複的資料庫操作。 如微軟的SQLHelper。cs 或動軟的DBUtility/DbHelperSQL等,為DAL提供訪問資料庫的輔助工具類。
這樣簡單三層出來了。 所以有兩個資料夾 database 和utility;
database 下有 BLL和 DAL。因為WEB 程式(aspx或jsp)是表示層。所有不放這裡。
utility 下有 Common 類和 DBUtility 類。Common 類是通用的輔助工具類。
DBUtility 類是資料訪問類。
而WEB 中aspx頁面Using 對應的 database 中的類。是因為。引用了。才能用啊。 而引用程式集。可以在 “引用”--“右鍵” 新增引用中做。
如果想再瞭解。請見下一篇轉載的大話簡單三層。
一個三層架構的小例子:註冊新使用者。
先寫模組的實體類,是資料庫中表的抽象,假設資料庫中註冊資訊只有賬號,密碼兩個欄位。那麼抽象到實體類就是這樣:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Entity
{
class UserInfo
{
public string UserName { get; set; } //C#3.0中屬性構造器的新寫法;
public string UserPwd { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Entity
{
class UserInfo
{
public string UserName { get; set; } //C#3.0中屬性構造器的新寫法;
public string UserPwd { get; set; }
}
}
再寫DAL層:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Data.SqlClient; using Entity; //這裡新增對Entity實體類的引用; namespace DAL { public class UserDAL { //在該類中,為了方便,一般會構造一個DataBaseFactory,方便進行程式碼的操作。所以以下程式碼僅為邏輯實現,不代表程式碼正確。 public bool AddUser(UserInfo uInfo) //這裡將實體類作為引數傳入; { string sqlStr="INSERT INTO UserInfo(Name,Pwd) VALUES(@name,@pwd)"; SqlCommand cmd=new SqlCommand(sqlStr); cmd.Parameters.Clear(); cmd.Parameters.Add("@name", SqlDbType.NVarChar, 50).Value = uInfo.UserName; //呼叫實體類的屬性 cmd.Parameters.Add("@pwd", SqlDbType.NVarChar, 50).Value = uInfo.UserPwd; return Convert.ToInt32(cmd.ExecuteNonQuery()) > 0 ? true : false; } public DataTable GetUserInfo(string name) //根據使用者名稱獲得使用者的具體資訊 { string sqlStr="SELECT * FROM UserInfo WHERE Name=@name"; SqlCommand cmd=new SqlCommand(sqlStr); cmd.Parameters.Clear(); cmd.Parameters.Add("@name", SqlDbType.NVarChar, 50).Value = name; SqlDataAdapter sda = new SqlDataAdapter(cmd); DataSet ds=new DataSet(); sda.Fill(ds,"UserInfo"); return ds.Tables["UserInfo"]; } } } using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using Entity; //這裡新增對Entity實體類的引用;
namespace DAL
{
public class UserDAL
{
//在該類中,為了方便,一般會構造一個DataBaseFactory,方便進行程式碼的操作。所以以下程式碼僅為邏輯實現,不代表程式碼正確。
public bool AddUser(UserInfo uInfo) //這裡將實體類作為引數傳入;
{
string sqlStr="INSERT INTO UserInfo(Name,Pwd) VALUES(@name,@pwd)";
SqlCommand cmd=new SqlCommand(sqlStr);
cmd.Parameters.Clear();
cmd.Parameters.Add("@name", SqlDbType.NVarChar, 50).Value = uInfo.UserName; //呼叫實體類的屬性
cmd.Parameters.Add("@pwd", SqlDbType.NVarChar, 50).Value = uInfo.UserPwd;
return Convert.ToInt32(cmd.ExecuteNonQuery()) > 0 ? true : false;
}
public DataTable GetUserInfo(string name) //根據使用者名稱獲得使用者的具體資訊
{
string sqlStr="SELECT * FROM UserInfo WHERE Name=@name";
SqlCommand cmd=new SqlCommand(sqlStr);
cmd.Parameters.Clear();
cmd.Parameters.Add("@name", SqlDbType.NVarChar, 50).Value = name;
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataSet ds=new DataSet();
sda.Fill(ds,"UserInfo");
return ds.Tables["UserInfo"];
}
}
}
再寫BLL層:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Entity; //新增對Entity類庫的引用
using DAL; //新增對DAL類庫的引用
namespace BLL
{
public class UserBLL
{
public static bool AddUser(UserInfo uInfo) //BLL層的方法多為靜態方法,DAL層也可以為靜態方法。
{
UserDAL uDal = new UserDAL();
DataTable dTable = uDal.GetUserInfo(uInfo.UserName);
if (dTable.Rows.Count > 0) //這裡對註冊使用者有一個判斷,從DAL層中先通過註冊名獲得使用者的具體資訊,若可以獲得則證明該使用者名稱已被註冊,返回false;
return false;
else
return uDal.AddUser(uInfo);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Entity; //新增對Entity類庫的引用
using DAL; //新增對DAL類庫的引用
namespace BLL
{
public class UserBLL
{
public static bool AddUser(UserInfo uInfo) //BLL層的方法多為靜態方法,DAL層也可以為靜態方法。
{
UserDAL uDal = new UserDAL();
DataTable dTable = uDal.GetUserInfo(uInfo.UserName);
if (dTable.Rows.Count > 0) //這裡對註冊使用者有一個判斷,從DAL層中先通過註冊名獲得使用者的具體資訊,若可以獲得則證明該使用者名稱已被註冊,返回false;
return false;
else
return uDal.AddUser(uInfo);
}
}
}
最後構建UI層程式碼,即我們的aspx.cs頁面程式碼,該層應該直接呼叫BLL層的方法。該頁面引用BLL和Entity的名稱空間,並向Button控制元件註冊事件:
protected void btnRegister_OnClick(object sender, EventArgs e)
{
UserInfo uInfo = new UserInfo(textUserName.text, textUserPwd.text);
if (UserBLL.AddUser(uInfo))
Response.Write("註冊成功!");
else
Response.Write("註冊失敗!");
}
protected void btnRegister_OnClick(object sender, EventArgs e)
{
UserInfo uInfo = new UserInfo(textUserName.text, textUserPwd.text);
if (UserBLL.AddUser(uInfo))
Response.Write("註冊成功!");
else
Response.Write("註冊失敗!");
}
這樣一個小的三層架構程式就出來了。
這個程式中,操作的實體為UserInfo表的抽象。在DAL層進行了AddUser()的方法,在BLL層也進行了AddUser()的方法,唯一的區別是BLL層做了邏輯判斷,如果使用者名稱存在,則註冊失敗。
三層架構的特點:
1.資料庫訪問層(DAL)僅提供對資料庫的CRUD操作,而不管操作後的結果,也不管邏輯過程(譬如同名使用者,不合法使用者名稱)。
2.業務邏輯層(BLL)不會直接與資料庫互動,他與資料庫的互動是通過DAL提供的方法。在呼叫這些方法前,要加入自己的邏輯判斷或者業務處理。另外業務邏輯層(BLL)還有可能不會去呼叫DAL層的方法,而是進行其他業務處理。
3.使用者介面層(UI)層是不會呼叫DAL層的,他只呼叫BLL層提供的方法,再由BLL層自己決定是否繼續呼叫DAL層。
這個例子可以看出三層架構的優點就是結構清晰,容易擴充套件與維護。缺點就是,複雜。僅僅一個註冊使用者,就這麼麻煩,所以對於小專案來說,費這麼大勁換取一個相對較清晰的分層結構是不划算的。
轉載請註明出處:csdn-mark
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/mark4ever/archive/2011/04/05/6302353.aspx 有一部分,也是我自己添的哈。嘿嘿