三层视频看完之后,就照着例子悄悄的敲,敲的不专心,又返回来看视频,继续敲。其实,第一次敲的比较盲目,没太理解一些语句,和逻辑。然后师傅就过来给我串了串,然后,就感觉豁然开朗了,视频中的小例子,在U,B,D层是通过传参数UserName,和Password两个参数进行的。师傅有要求传个实体,最好能加上抽象工厂+反射,为了变更数据库时使用。接下来就说一下就说一下,具体实现过程:
一.先说一下,从视频中学到的三层概念:
U层作用(3个):
1.展示给用户界面
2.识别用户操作
3.采集用户输入信息
不包含任何业务逻辑
B层作用:
先获取U层的数据和指令,然后执行业务逻辑,或通过DAL写入数据源
最后,还要将D层必要数据传给U层。
D层作用:
提供基本的数据访问,不包含任何业务逻辑。
先看一下我的包图:
在这里解说一下:
外观模式;一般放在设计初期,加在U层和B层,B层和D 层之间,这样可以提供一个简单接口,使层与层之间耦合度降低。在这里就是,利用这个接口降低,U层与B层之间的耦合。
实体层:视频版的登陆窗体数据简单,传的是参数。如果有很多数据,都较麻烦了,不如传个实体,将参数都放在实体里面。
抽象工厂+反射:作用就是为了更换数据库。只需在配置文件中更改数据库就能进行自动更改,而无需在层中大量手动修改代码。从抽象工厂中出来的就是,一个具体的D层的类了。
接口:开始对这个IDAL没能很好的理解,其实,就是在更换数据库时,减少写入D层不同类中的代码重覆。
这是我的解决方案:
U层:得到,用户输入的username ,和password并以实体形式传给外观层的方法(传给外观层)。
Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
Dim username = txtUserName.Text.Trim()
Dim password = txtPassword.Text
Dim user1 As New Model.UserInfo
user1.UserName = username
user1.Password = password
Dim userFac As New Facade.LoginFAC
Dim str As String
str = userFac.strRusult(user1)'等号右边是将user1传给外观层(正向),等号左边现在是空的。
Select Case str '将传回来的字符串给str后,进行Select语句。
Case "用户不存在"
MessageBox.Show("用户不存在,请重新输入!")
txtUserName.Text = ""
txtPassword.Text = ""
txtUserName.Focus()
Case "密码不正确"
MessageBox.Show("密码不正确,请重新输入!")
txtPassword.Text = ""
txtPassword.Focus()
Case "登陆成功!"
MessageBox.Show("恭喜你,登陆成功!")
Case "登陆次数达到三次"
MessageBox.Show("登陆次数达到三次, 退出重新进入!")
Me.Close()
End Select
End Sub
Facade层:U层里面Select有四个分支(即四种情况),而我的系统暂时只想考虑前三种情况,所以在外观层里面就根据需要,放了三种。使U层简化,降低了耦合。
Imports BLL
Public Class LoginFAC
Public Function strRusult(user As Model.UserInfo) As String
Dim checkUser As New BLL.CheckUser
If Not checkUser.IsExist(user) Then'调用B层方法,将user传给B层
Return "用户不存在"
ElseIf Not checkUser.CheckPassword(user) Then
Return "密码不正确"
Else
Return "登陆成功!"
End If
End Function
End Class
B层:进行逻辑处理,进行用户名和密码的逻辑处理。
Imports Factory
Imports IDAL
Public Class CheckUser
Public Function IsExist(ByVal user As Model.UserInfo) As Boolean
Dim Iuser As IDAL.IUserInfo
Dim FacUser As New Factory.FactoryDB
Iuser = FacUser.CreatIUser()
If Iuser.QueryUserInfo(user).UserName = "" Then
Return False
Else
Return True
End If
End Function
Function CheckPassword(ByVal user As Model.UserInfo) As Boolean
Dim Iuser As IDAL.IUserInfo
Dim FacUser As New Factory.FactoryDB
Iuser = FacUser.CreatIUser()
If Iuser.QueryUserInfo(user).Password = "" Then
Return False
Else
Return True
End If
End Function
End Class
D层:进行数据库连接。在这里利用配置文件自动连接数据库。
D层的每个类都实现了,接口中的方法。
Imports Model
Imports IDAL
Imports System.Data.SqlClient
Public Class SqlUserDAO : Implements IUserInfo
'调用配置文件与数据库连接
Dim strconn As String = System.Configuration.ConfigurationSettings.AppSettings("conStr")
Dim conn As SqlConnection = New SqlConnection(strconn)
Public Function QueryUserInfo(ByVal user As UserInfo) As UserInfo Implements IUserInfo.QueryUserInfo
Dim cmd As New SqlCommand
cmd = conn.CreateCommand()
cmd.CommandText = "select * from Users where UserName=@username and Password=@password"
cmd.CommandType = CommandType.Text
cmd.Parameters.Add(New SqlParameter("@username", user.UserName))
cmd.Parameters.Add(New SqlParameter("@password", user.Password))
conn.Open()
Dim reader As SqlDataReader
reader = cmd.ExecuteReader
Dim user3 As New Model.UserInfo
'user3 = Nothing
While (reader.Read())
user3.UserName = reader.GetString(1)
user3.Password = reader.GetString(2)
End While
conn.Close()
Return user3
End Function
End Class
接口层:
Public Interface IUserInfo
Function QueryUserInfo(ByVal user As Model.UserInfo) As Model.UserInfo
End Interface
抽象工厂层:利用配置文件选取数据库,并创建一个接口类型。
Public Class FactoryDB
Private Shared ReadOnly AssemblyName As String = "DAL" '数据程序集名称
Dim strDB As String = System.Configuration.ConfigurationSettings.AppSettings("DB")
Public Function CreatIUser() As IDAL.IUserInfo
Dim classname As String = "DAL" + "." + strDB + "UserDAO"
Return CType(Assembly.Load(AssemblyName).CreateInstance(classname), IDAL.IUserInfo)
End Function
End Class
配置文件:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key ="DB" value ="Sql"/>'更改字符串“Sql”为“Access”则可进行数据库的更换!
<add key ="conStr" value ="Server=tiger-PC;Database=Login;User ID=sa;Password=123456"/>'连接数据库字符串。
</appSettings>
</configuration>
总结:逻辑上貌似正确的,实现的过程中也遇到了一些问题,比如配置文件的时候,出现“未将对象引用配置到对象的实例”。具体问题原因和解决方法见我师父的博客:http://blog.csdn.net/u010924834/article/details/37995321。
三层,是机房重构的必经之路,深刻理解三层理念,才能做好机房重构。