標籤:
敲完了三層登入很長時間了,明白三層是怎麼傳遞的,但是就是總是無從下手的感覺,別人都說敲幾條線就明白了,但是,你懂得……這時我想起了米老師的一句話:不管怎麼樣,先聽去做,做完了再說自己的想法。如果總是不下手,就永遠不會進步。所以,我開始了登入的“七層”版。
先用一張包圖來看看這“七層”裡面是怎麼進行傳遞的:
由圖可知,這“七層‘就是在三層的基礎上繼續對U層、B層、D層進行解耦。本來在三層中是U層接收傳進來的資料,然後調用B層的方法,把資料傳給B層,之後B層調用D層的方法。但這並不是真正的解耦,因為當B層或者D層有所改動時,U層也會跟著進行改動。所以我們把三層結構改成了”七層“結構。
在U層和B層之間加了一個外觀層,讓外觀對U層和B層進行解耦,這樣U層就不知道B層的變化甚至不知道有B層就可以實現自己的功能。同理,我們在B層和D層之間添加了介面類,裡麵包括各種方法,這個方法的具體實現就寫在D層中,這樣B層和D層就能很好的解耦了。抽象工廠是為了以後方便更換資料庫。
首先建立下面的windows應用程式及類庫:
U層:
<span style="font-size:18px;">Imports JFBLL.LoginBLLImports JFEntity.LoginUserEntityImports FacadeImports System.Net.DnsPublic Class frmLogin Private Sub btnOk_Click(sender As Object, e As EventArgs) Handles btnOk.Click '判斷文字框 If txtUserID.Text = "" Then MessageBox.Show("請輸入使用者名稱!", "", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) txtUserID.Text = "" txtUserID.Focus() Exit Sub ElseIf txtPwd.Text = "" Then MessageBox.Show("請輸入密碼!", "", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) txtPwd.Text = "" txtPwd.Focus() Exit Sub End If Try Dim FacadeLogin As New Facade.LoginFacade '定義一個外觀層對象 Dim UserInfo As New JFEntity.LoginUserEntity() '定義一個實體 '將文字框中的輸入內容傳給實體 UserInfo.UserID = txtUserID.Text.Trim() UserInfo.Password = txtPwd.Text.Trim() Dim strResult1 As Boolean strResult1 = FacadeLogin.CheckUser(UserInfo) '將U層的文字框的內容傳入外觀層,然後通過外觀曾傳入B層進行判斷 If strResult1 = False Then MsgBox("使用者不存在!") txtUserID.Text = "" txtPwd.Text = "" txtUserID.Select() txtUserID.Focus() End If Dim table As DataTable table = FacadeLogin.CheckPwd(UserInfo) If Trim(txtPwd.Text) = Trim(table.Rows(0).Item(3)) Then MsgBox("登入成功!") 'frmMain.Show() txtUserID.Text = "" txtPwd.Text = "" End If Catch ex As Exception MsgBox("使用者不存在或密碼不正確!") txtUserID.Text = "" txtPwd.Text = "" txtUserID.Select() txtUserID.Focus() End Try End Sub Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click Me.Close() End Sub Private Sub frmLogin_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim Address() As System.Net.IPAddress Address = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList txtcomputer.Text = System.Net.Dns.GetHostName().ToString() End SubEnd Class</span>
外觀層:
<span style="font-size:18px;">'/*****************************************'類 名 稱:LoginFacade'命名空間:Facade'建立時間:2015/6/7 16:18:00'作 者:邢玉'小 組:'修改時間:'修 改 人:'版 本 號:v1.0.0’******************************************Imports JFBLLImports JFEntityPublic Class LoginFacade ''' <summary> ''' 檢查使用者名稱 ''' </summary> ''' <param name="UserInfo"></param> ''' <returns></returns> ''' <remarks></remarks> Public Function CheckUser(ByVal UserInfo As JFEntity.LoginUserEntity) As Boolean Dim IsUserExists As New JFBLL.LoginBLL() Dim flag As Boolean flag = IsUserExists.IsUserExists(UserInfo) If flag = True Then Return True Else Return False End If Return flag End Function ''' <summary> ''' 檢查密 ''' </summary> ''' <param name="UserInfo"></param> ''' <returns></returns> ''' <remarks></remarks> Public Function CheckPwd(ByVal UserInfo As JFEntity.LoginUserEntity) As DataTable Dim IsPwd As New JFBLL.LoginBLL() Dim table As DataTable table = IsPwd.IsPwdright(UserInfo) Return table End FunctionEnd Class</span>
工廠:
<span style="font-size:18px;">'/*****************************************'類 名 稱:LoginFactory'命名空間:Factory'建立時間:2015/6/7 16:18:59'作 者:邢玉'小 組:'修改時間:'修 改 人:'版 本 號:v1.0.0’******************************************Imports System.Configuration '添加對設定檔的引用Imports System.Reflection '添加對反射的應用Imports IDALPublic Class LoginFactory '讀設定檔,D層的每個類都在設定檔裡對應一個KEY '下面這句是把key設成變數,然後再下面的方法中只用這個變數就可以應用D層的這個類了。 Dim strDB As String = System.Configuration.ConfigurationSettings.AppSettings("DBString") ''' <summary> ''' 執行個體化一個JFDAL中的User_Info表的類 ''' </summary> ''' <returns></returns> ''' <remarks></remarks> Public Shared Function CreateUserInfo() As IuserinfoDAL 'CType是一個內嵌函式,將前部分的運算式轉換為後面的類型 Return CType(Assembly.Load("JFDAL").CreateInstance("JFDAL" & "." & "UserDAL"), IuserinfoDAL) '返回IuserinfoDAL 'Return CType(Assembly.Load("JFDAL").CreateInstance("JFDAL.LoginDAL"), IuserinfoDAL) End FunctionEnd Class</span>
介面:
<span style="font-size:18px;">Imports JFEntityPublic Interface IuserinfoDAL 'UserInfo為使用者資訊的實體,是由實體類執行個體化來的。 '即所謂的傳實體。 '此介面定義了一個方法,用以檢查使用者是否存在 Function selectUser(ByVal UserInfo As JFEntity.LoginUserEntity) As DataTable ''' <summary> ''' 添加使用者 ''' </summary> ''' <param name="UserInfo"></param> ''' <returns></returns> ''' <remarks></remarks> Function AddUser(ByVal UserInfo As LoginUserEntity) As DataTableEnd Interface</span>
B層:
<span style="font-size:18px;">'/*****************************************'類 名 稱:LoginBLL'命名空間:JFBLL'建立時間:2015/6/7 16:12:49'作 者:邢玉'小 組:'修改時間:'修 改 人:'版 本 號:v1.0.0’******************************************Imports FactoryImports IDALImports JFEntityPublic Class LoginBLL '檢查使用者是否存在 Public Function IsUserExists(ByVal UserInfo As JFEntity.LoginUserEntity) As Boolean 'Dim factory As New Factory.LoginFactory() Dim Iuser As IDAL.IuserinfoDAL '調用“建立使用者”的Factory 方法 Iuser = Factory.LoginFactory.CreateUserInfo Dim table As New DataTable Dim flag As Boolean table = Iuser.selectUser(UserInfo) '由於在sqlHelper中返回的形式為表格形式(adataset.Tables(0)),且開頭第一列表示為0,所以Item(0)則代表使用者名稱 If table.Rows(0).Item(0) = 0 Then flag = False Else flag = True End If Return flag End Function查看密碼是否正確 Public Function IsPwdright(ByVal UserInfo As JFEntity.LoginUserEntity) As DataTable 'Dim factory As New Factory.LoginFactory() Dim Iuser As IDAL.IuserinfoDAL Dim table As DataTable '中間變數,用於儲存D層查詢到的資料 Iuser = Factory.LoginFactory.CreateUserInfo '調用工廠的createUserInfo方法建立Iuser table = Iuser.selectUser(UserInfo) '調用介面的方法selectuser Return table End FunctionEnd Class</span>
D層:
<span style="font-size:18px;">'/*****************************************'類 名 稱:LoginDAL'命名空間:JFDAL'建立時間:2015/6/7 16:01:07'作 者:邢玉'小 組:'修改時間:'修 改 人:'版 本 號:v1.0.0’******************************************Imports System.Data.SqlClient 'system.Data.SqlClient 命名空間是SQLSever的.NET Framework資料提供者'SQL Sever 的.NET Framework資料提供者描述了一個類集合,這個類集合用於訪問託管空間中的SQL Sever資料庫Imports JFEntityImports IDALImports SQLHelperPublic Class UserDAL : Implements IDAL.IuserinfoDAL '實現介面中的方法 '聲明並執行個體化SQLHelper類 Private SqlHelper As SQLHelper.sqlHelper = New SQLHelper.sqlHelper() Public Function selectUser(UserInfo As LoginUserEntity) As DataTable Implements IuserinfoDAL.selectUser Dim Sql As String Dim table As DataTable '中間變數,用於儲存從資料庫中尋找到的資訊 Dim sqlParams As SqlParameter() = {New SqlParameter("@UserID", UserInfo.UserID), New SqlParameter("@Password", UserInfo.Password)} '聲明並執行個體化參數數組 Sql = "select * from User_Info where [email protected] and [email protected]" '下句為調用SqlHelper類中的GetDataTable() 方法來執行查詢,並擷取傳回值 table = SqlHelper.GetDataTable(Sql, CommandType.Text, sqlParams) Return table End FunctionEnd Class</span>
Entity:
<span style="font-size:18px;">'/*****************************************'類 名 稱:LoginUserEntity'命名空間:JFEntity'建立時間:2015/6/7 16:06:11'作 者:邢玉'小 組:'修改時間:'修 改 人:'版 本 號:v1.0.0’******************************************Public Class LoginUserEntity '變數名字比資料庫中的欄位名字多一個_ Private _UserName As String Private _Password As String Private _UserID As String Private _Level As String Private _Holder As String '以下為可讀寫屬性 '名字和資料庫中的一樣 Public Property UserName() As String Get Return _UserName End Get Set(ByVal value As String) _UserName = value End Set End Property Public Property UserID() As String Get Return _UserID End Get Set(ByVal value As String) _UserID = value End Set End Property Public Property Password() As String Get Return _Password End Get Set(ByVal value As String) _Password = value End Set End Property Public Property Level As String Get Return _Level End Get Set(ByVal value As String) _Level = value End Set End Property Public Property Holder As String Get Return _Holder End Get Set(ByVal value As String) _Holder = value End Set End PropertyEnd Class</span>
SQLhelper:
<span style="font-size:18px;">'/*****************************************'類 名 稱:sqlHelper'命名空間:SQLHelper'建立時間:2015/6/7 16:48:39'作 者:邢玉'小 組:'修改時間:'修 改 人:'版 本 號:v1.0.0’******************************************Imports System.Data.SqlClientImports System.ConfigurationImports System.DataPublic Class sqlHelper Private Shared ConnectionString As String = ConfigurationManager.AppSettings("ConnString") ''' <summary> ''' 執行帶參數的查詢操作 ''' </summary> ''' <param name="cmdTxt">參數cmdTxt為所要執行的sql語句</param> ''' <param name="cmdType">查詢時的查詢方式</param> ''' <param name="paras">查詢時的命令參數paras</param> ''' <returns>查詢後以表的方式返回,如下面的adataset.Tables(0)</returns> ''' <remarks></remarks> Public Shared Function GetDataTable(ByVal cmdTxt As String, ByVal cmdType As CommandType, ByVal paras As SqlParameter()) As DataTable Dim conn As SqlConnection = New SqlConnection(ConnectionString) '建立資料庫連接 Dim cmd As SqlCommand '定義命令變數cmd Dim adaptor As SqlDataAdapter '定義資料配接器 Dim adataset As DataSet '定義並執行個體化資料緩衝區對象,即從資料庫傳入的對象 cmd = New SqlCommand(cmdTxt, conn) '在conn上面執行執行個體化命令變數,並執行語句cmdtype cmd.CommandType = cmdType '執行命令的類型 cmd.Parameters.AddRange(paras) '命令執行時的參數 adaptor = New SqlDataAdapter(cmd) '將結果綁定到資料配接器變數adaptor上面 adataset = New DataSet Try '如果資料庫連接狀態為關閉則將其開啟 If conn.State = ConnectionState.Closed Then conn.Open() End If adaptor.Fill(adataset) '向adaptor對象中填充查詢的資料 Catch ex As Exception '錯誤處理程式,出錯則提示 MsgBox(ex.Message, , "資料庫操作") Finally '如果串連狀態為開啟則將其關閉,釋放記憶體 If conn.State = ConnectionState.Open Then conn.Close() End If End Try '以表格形式返回結果 Return adataset.Tables(0) End Function Function GetDataTable() As DataTable Throw New NotImplementedException End FunctionEnd Class</span>
我們所說的“七層”不過就是對三層的結構進行了進一步的解耦,但是仍然是三層的思想,大家不要以為層多了就解耦了,其實三層的思想就是一個解耦的思想。
對於SQLhelper研究的不是很深刻,所以只是寫了一個,等到後面的時候會進一步完善的……
機房收費系統——“七層”登入