三層架構 詳解

前言

當看到一個陌生的名詞時你會怎麼想?what?way?how? 現在就按照這個思維框架走進“三層架構”。

什麼是三層架構?

在軟件體系架構設計中,分層式結構是最常見,也是最重要的一種結構。微軟推薦的分層式結構一般分爲三層,從下至上分別爲:數據訪問層、業務邏輯層(又或稱爲領域層)、表示層。

1、表示層(UI):通俗講就是展現給用戶的界面,即用戶在使用一個系統的時候他的所見所得。

2、業務邏輯層(BLL):針對具體問題的操作,也可以說是對數據層的操作,對數據業務邏輯處理。

3、數據訪問層(DAL):該層所做事務直接操作數據庫,針對數據的增添、刪除、修改、查找等。
微軟的DNA架構定義了三個層:表示層(presentation),業務邏輯層(business),和數據訪問層(data access)。具體又分爲:界面外觀層、界面規則層、業務接口層、業務邏輯層、實體層、數據訪問層、數據存儲層共七層,其具體的調用如下圖所示:
在這裏插入圖片描述

爲什麼要用三層架構?

對於一個簡單的應用程序來說,代碼量不是很多的情況下,一層結構或二層結構開發完全夠用,沒有必要將其複雜化,如果對一個複雜的大型系統,設計爲一層結構或二層結構開發,那麼這樣的設計存在很嚴重缺陷。

分層開發其實是爲大型系統服務的。在開發過程中,初級程序人員出現相似的功能經常複製代碼,那麼同樣的代碼寫那麼多次,不但使程序變得冗長,更不利於維護,一個小小的修改或許會涉及很多頁面,經常導致異常的產生使程序不能正常運行。最主要的面向對象的思想沒有得到絲毫的體現,打着面向對象的幌子卻依然走着面向過程的道路。

意識到這樣的問題,初級程序人員開始將程序中一些公用的處理程序寫成公共方法,封裝在類中,供其它程序調用。例如寫一個數據操作類,對數據操作進行合理封裝,在數據庫操作過程中,只要類中的相應方法(數據添加、修改、查詢等)可以完成特定的數據操作,這就是數據訪問層,不用每次操作數據庫時都寫那些重複性 的數據庫操作代碼。在新的應用開發中,數據訪問層可以直接拿來用。面向對象的三大特性之一的封裝性在這裏得到了很好的體現。現在找到了面向對象的感覺,代碼量較以前有了很大的減少,而且修改的時候也比較方便,也實現了代碼的重用性。

優缺點:

(一)優點

1、開發人員可以只關注整個結構中的其中某一層;

2、可以很容易的用新的實現來替換原有層次的實現;

3、可以降低層與層之間的依賴;

4、有利於標準化;

5、利於各層邏輯的複用。

(二)缺點

1、降低了系統的性能。這是不言而喻的。如果不採用分層式結構,很多業務可以直接造訪數據庫,以此獲取相應的數據,如今卻必須通過中間層來完成。

2、有時會導致級聯的修改。這種修改尤其體現在自上而下的方向。如果在表示層中需要增加一個功能,爲保證其設計符合分層式結構,可能需要在相應的業務邏輯層和數據訪問層中都增加相應的代碼。

3、增加了開發成本。

怎麼用三層架構?

不是所有的系統都需要使用三層架構,在一開始學習這塊知識的時候有可能會存在誤區。對於簡單的問題我們沒有必要把它複雜化,甚至有可能會畫蛇添足、多此一舉。

不需要使用的情況:

        1業務邏輯簡單。 

        2、沒有真正的數據存儲層。

需要使用的情況:

既有數據訪問層DAL又有業務邏輯層BLL,也就是說當業務複雜到一定程度後,數據需要單獨的存儲到相對獨立的介質中時,需要把數據訪問脫離開業務單獨存在,把業務脫離開UI單獨存在,UI達到業務只需要呼叫業務訪問層即可實現跟用戶訪問的交互。這種情況下我們才使用三層結構。

實例演練:

現在有一個積分系統,學生每登錄一次可獲得10積分獎勵。代碼入下:
UI層:

 private void btnLogin_Click(object sender, EventArgs e)
        {
            
            string userName=txtUsername.Text.Trim();
            string password=txtPassword.Text;
            LoginBll.LoginManager mgr = new LoginBll.LoginManager();   //實例化一個業務層的LoginManager,用於邏輯判斷
            LoginModel.UserInfo user= mgr.UserLogin(userName, password);  //實例化一個業務層的Model,用於給userlogin賦值name,password
            MessageBox.Show("登錄用戶: " + user.UserName);   //顯示登錄信息
           
        }

BLL層:

namespace LoginBll
{
    //管理登錄類,用於判斷用戶是否登陸成功
    public class LoginManager
    {
        //UI層傳遞的是UserInfo方法,數據是Username,password
        public LoginModel.UserInfo UserLogin(string userName, string password)   //UserLogin方法,判斷登錄信息是否正確
        {
            
            LoginDAL.UserDAO uDao = new LoginDAL.UserDAO();  //實例化一個數據層登錄
            LoginModel.UserInfo user = uDao.SelectUser(userName, password);  //實例化一個Model,用於給數據層的SelectUser賦值
 
            if (user!=null)
            {
                LoginDAL.SocreDAO sDao = new LoginDAL.SocreDAO();
                sDao.UpdateScore(user.ID ,userName, 10);//增加積分
                return user;
            }
            else
            {
                throw new Exception("登錄失敗");
            }
        }
    }

DAL層:

 class DBUtil
    {
        public static string ConnString = @"Server= (Local);Database=Login;User ID=sa;Password=123";
    }
 
 public class SocreDAO
    {
        public void UpdateScore(int ID,string userName,int value)
        {
            using (SqlConnection conn=new SqlConnection(DBUtil.ConnString ))
            {
                SqlCommand cmd = conn.CreateCommand();
                cmd.CommandText = @"INSERT INTO SCORES(UserName,Score) Values(@UserName,@Score)";
                cmd.Parameters.Add(new SqlParameter("@ID", ID));
                cmd.Parameters.Add(new SqlParameter ("@UserName",userName ));
                cmd.Parameters.Add(new SqlParameter("@Score", value ));
                conn.Open();
                //執行sql句,返回受影響行數
                cmd.ExecuteNonQuery();
                 
            }
           
        }
    }
 
 
public class UserDAO
    {
        public LoginModel.UserInfo SelectUser(string userName, string password)
        {
            using (SqlConnection conn = new SqlConnection(DBUtil.ConnString))//建立數據庫連接
            {
                SqlCommand cmd = conn.CreateCommand(); // 創建命令
               // cmd.CommandText = @"SELECT ID,UserName,Password,Email FROM USERS WHERE UserName=@UserName AND Password=@Password "; //設置操作語句
                cmd.CommandType = CommandType.Text;
                cmd.Parameters.Add(new SqlParameter("@UserName", userName));
                cmd.Parameters.Add(new SqlParameter("@Password", password));
 
                cmd.CommandText = @"SELECT ID,UserName,Password,Email FROM USERS WHERE UserName=@UserName AND Password=@Password "; //設置操作語句
 
                conn.Open();//打開連接
                //創建數據讀取對象,循環讀取數據
                SqlDataReader reader = cmd.ExecuteReader();  //此方法用於用戶進行的查詢操作,使用SqlDataReader對象的Read();方法進行逐行讀取。
 
                LoginModel.UserInfo user = null;
                while (reader.Read())
                {
                    if (user==null)
                    {
                        user = new LoginModel.UserInfo();
                    }
                    user.ID =reader.GetInt32(0); //獲取指定列的32位有符號整數形式的值 
                    user.UserName = reader.GetString(1);
                    user.Password = reader.GetString(2);
                    if (!reader.IsDBNull (3))
                    {
                        user.Email = reader.GetString(3);
                    }
                }
                return user;
            }
        }
    }

實體層:

 //數據模型,用於三層之間傳輸數據
    public class UserInfo
    {
        public int ID { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
    }

原文鏈接:https://blog.csdn.net/duyusean/article/details/70882262

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章