敲完了三层登录很长时间了,明白三层是怎么传递的,但是就是总是无从下手的感觉,别人都说敲几条线就明白了,但是,你懂得……这时我想起了米老师的一句话:不管怎么样,先听去做,做完了再说自己的想法。如果总是不下手,就永远不会进步。所以,我开始了登录的“七层”版。
先用一张包图来看看这“七层”里面是怎么进行传递的:
由图可知,这“七层‘就是在三层的基础上继续对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.LoginBLL
Imports JFEntity.LoginUserEntity
Imports Facade
Imports System.Net.Dns
Public 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 Sub
End Class</span>
外观层:
<span style="font-size:18px;">'/*****************************************
'类 名 称:LoginFacade
'命名空间:Facade
'创建时间:2015/6/7 16:18:00
'作 者:邢玉
'小 组:
'修改时间:
'修 改 人:
'版 本 号:v1.0.0
’******************************************
Imports JFBLL
Imports JFEntity
Public 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 Function
End 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 IDAL
Public 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 Function
End Class
</span>
接口:
<span style="font-size:18px;">Imports JFEntity
Public 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 DataTable
End Interface
</span>
B层:
<span style="font-size:18px;">'/*****************************************
'类 名 称:LoginBLL
'命名空间:JFBLL
'创建时间:2015/6/7 16:12:49
'作 者:邢玉
'小 组:
'修改时间:
'修 改 人:
'版 本 号:v1.0.0
’******************************************
Imports Factory
Imports IDAL
Imports JFEntity
Public Class LoginBLL
'检查用户是否存在
Public Function IsUserExists(ByVal UserInfo As JFEntity.LoginUserEntity) As Boolean
'Dim factory As New Factory.LoginFactory()
Dim Iuser As IDAL.IuserinfoDAL
'调用“创建用户”的工厂方法
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 Function
End 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 JFEntity
Imports IDAL
Imports SQLHelper
Public 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 Function
End 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 Property
End Class
</span>
SQLhelper:
<span style="font-size:18px;">'/*****************************************
'类 名 称:sqlHelper
'命名空间:SQLHelper
'创建时间:2015/6/7 16:48:39
'作 者:邢玉
'小 组:
'修改时间:
'修 改 人:
'版 本 号:v1.0.0
’******************************************
Imports System.Data.SqlClient
Imports System.Configuration
Imports System.Data
Public 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 Function
End Class
</span>
我们所说的“七层”不过就是对三层的结构进行了进一步的解耦,但是仍然是三层的思想,大家不要以为层多了就解耦了,其实三层的思想就是一个解耦的思想。
对于SQLhelper研究的不是很深刻,所以只是写了一个,等到后面的时候会进一步完善的……