纯三层的机房重构终于敲完了,但是还需要加设计模式,这又是一道难题。研究了半天的时间,终于对七层的运行步骤熟悉了一些,也对抽象工厂加反射和配置文件了解的更多了一些,下面就看看我的新认识。
这是七层的包图,说是七层,但是七层并不是严格意义上的七层,只不过在三层的基础上加上了工厂、外观和接口,用到设计模式的地方多了自然就形成了一层,所以就有了现在的七层。
各层代码
界面层
分层之后界面层的功能很简单,不能再有逻辑判断,可以有些简单的是否为空或者是否为数字等。
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class frmLogin ''' <summary> ''' 登录 ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click Dim lFac As New Facade.loginFac Dim result As String Dim User As New Entity.UserInfo User.ID = txtID.Text.Trim User.Password = txtPwd.Text.Trim result = lFac.Confirm(User) Select Case result Case "该用户不存在!" txtID.Focus() txtID.SelectAll() Case "密码错误!" txtPwd.Focus() txtPwd.SelectAll() Case "登录成功!" MsgBox("登录成功!") End Select End Sub End Class</span></span></span></span>
外观层
我理解的外观层其实放的是U层需要用到的方法,这样U层就只跟外观层打交道就好了,它不需要知道具体实现,这样就很好的做到了解耦。
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class loginFac ''' <summary> ''' 验证用户 ''' </summary> ''' <param name="User"></param> ''' <returns></returns> ''' <remarks></remarks> Public Function Confirm(ByVal User As Entity.UserInfo) As String Dim ConfirmUser As New BLL.LoginBLL If Not ConfirmUser.IsExist(User) Then Return "该用户不存在!" Else If Not ConfirmUser.ConfirmPwd(User) Then Return "密码错误!" Else Return "登录成功!" End If End If End Function End Class</span></span></span></span>
逻辑判断层
逻辑判断层顾名思义,就是进行逻辑判断的,登录时的判断用户是否存在和密码输入是否正确就在B层进行判断。
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class LoginBLL ''' <summary> ''' 验证用户是否存在 ''' </summary> ''' <param name="User"></param> ''' <returns>布尔值</returns> ''' <remarks></remarks> Public Function IsExist(ByVal User As Entity.UserInfo) As Boolean Dim IUser As IDAL.IUserInfo Dim factory As New Factory.DataAccess IUser = factory.CreateUserInfo() If IUser.SelectUser(User)(0).ID = "" Then Return False Else Return True End If End Function ''' <summary> ''' 验证密码是否正确 ''' </summary> ''' <param name="User"></param> ''' <returns>布尔值</returns> ''' <remarks></remarks> Public Function ConfirmPwd(ByVal User As Entity.UserInfo) As Boolean Dim IUser As IDAL.IUserInfo Dim factory As New Factory.DataAccess IUser = factory.CreateUserInfo() If IUser.SelectUser(User)(0).Password = "" Then Return False Else Return True End If End Function End Class</span></span></span></span>
接口
接口是定义一个方法名,为了让D层去实现,我觉得接口的存在也很好的做到了解耦,在B层就只需要声明一个接口,具体实现也不需要了解。
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;">Public Interface IUserInfo Function SelectUser(ByVal User As Entity.UserInfo) As List(Of Entity.UserInfo) End Interface</span></span></span></span>
工厂
工厂的功能就是批量的产生类,就像现实中的工厂,给了订单之后,就可以批量生产。其实接口和工厂就像现实生活中的老板和工厂,老板是联系顾客和工厂的中介,接口也同样。
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class DataAccess Dim strDB As String = System.Configuration.ConfigurationSettings.AppSettings("DB") ''' <summary> ''' 产生类 ''' </summary> ''' <returns></returns> ''' <remarks></remarks> Function CreateUserInfo() As IDAL.IUserInfo Return CType(Assembly.Load("DAL").CreateInstance("DAL.LoginDAL"), IDAL.IUserInfo) End Function End Class</span></span></span></span>
数据层
D层主要是和数据库打交道,将你想要的信息查询出来并返回,或者按照你的意愿更新数据库的信息,也就是数据库的增删改查。
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class LoginDAL : Implements IDAL.IUserInfo ''' <summary> ''' 查询Users表的信息 ''' </summary> ''' <param name="User"></param> ''' <returns>泛型集合</returns> ''' <remarks></remarks> Public Function SelectUser(ByVal User As Entity.UserInfo) As List(Of Entity.UserInfo) Implements IDAL.IUserInfo.SelectUser Dim helper As New SQLHelper Dim sql As String = "Select * From Users Where ID = '" & User.ID & "'" Dim dt As New DataTable Dim lUser As New List(Of Entity.UserInfo) dt = helper.ExecuteSelect(sql, CommandType.Text) lUser = ConvertHelper.ConverToList(dt, lUser) Return lUser End Function End Class</span></span></span></span>
利用反射换数据库
Assembly.Load("程序集名称").CreateInstance("命名空间.类名称")
程序集名称就是类库属性中的程序集名称,命名空间就是类库属性中的根命名空间,类名称就是该命名空间下的类名。利用反射换数据库的实质其实就是,如果要使用不同的数据库,D层就应该有不同的类,比如用Sql Server时类名为LoginDALSql,用Oracle时类名应该为LoginDALOra。因为数据库类型可以用配置文件中的字符串来变动,所以在配置文件中需这样写:
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="strConn" value="Server=localhost;DataBase=Login;User=sa;Password=0722"/> <add key="DB" value="Sql"/> </appSettings> </configuration></span></span></span></span>
然后工厂中的代码为
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class DataAccess Dim strDB As String = System.Configuration.ConfigurationSettings.AppSettings("DB") ''' <summary> ''' 利用反射 ''' </summary> ''' <returns></returns> ''' <remarks></remarks> Function CreateUserInfo() As IDAL.IUserInfo Return CType(Assembly.Load("DAL").CreateInstance("DAL.LoginDAL" & strDB), IDAL.IUserInfo) End Function End Class</span></span></span></span>
“DB”是读取的配置文件中的字符串,strDB是定义的换数据库的字符串,这样工厂返回的类名应该是“DAL.LoginDALSql”。如果要换数据库,只需要将配置文件的“Sql”换成“Ora”就行了,工厂返回的类名就是“DAL.LoginDALOra”,这样就可以实现不同数据库操作类的更换。
遇到的错误
登录中主要遇到了两个问题:
1、未能加载文件或程序集“DAL”或它的某一个依赖项。系统找不到指定文件
这个错误参照李社河师哥的一篇博客解决的:解决方法参考
2、配置系统未能初始化
这个问题网上有很多解决方法,其实最主要的原因就是配置文件写错了,可能是顺序错误或者什么的。我出现的错误是大小写的问题,应该写成大写的写成了小写,就这样就酿成了悲剧。
配置文件
在机房重构中主要用配置文件其实就是写数据库连接字符串,写配置文件时有一个顺序要求,configSections-->connectionStrings-->appSettings,
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;"><?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name ="" type =""/> </configSections> <connectionStrings> <add name="" connectionString="" providerName="" /> </connectionStrings> <appSettings> <add key="" value =""/> </appSettings> </configuration></span></span></span>上面是一个空的配置文件,只有加载格式没有内容。三者的顺序必须按照上面的前后顺序,否则也会出现“配置系统未能初始化”的错误。这三种方式都可以写连接数据库的字符串,只不过效果不太一样。比如,ConnectionStrings可以将连接数据库的字符串加密等等。另外,用不同的方式写连接字符串,读取配置文件的代码不同,如果用AppSettings写,代码就是
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;">System.Configuration.ConfigurationSettings.AppSettings("")</span></span>如果用ConnectionStrings来写的话,代码是
<span style="font-family:KaiTi_GB2312;font-size:18px;"><span style="font-family:KaiTi_GB2312;font-size:18px;">System.Configuration.ConfigurationSettings.ConnectionStrings("")</span></span>
需要的代码资源,可下载:七层登录实现
总结
对于自己学的东西,不管是什么东西,都要先着手去做,开始的时候不知道该怎么做,可能改了又改,可是就是这个过程才能让自己对它理解更深。另外,学什么东西不要只看到表面,不理解深层,这样容易卡在一个小问题上。