机房重构:三层到七层

来源:互联网 发布:linux 重启ssh 编辑:程序博客网 时间:2024/06/05 02:46

           经过了5天的努力,终于完成了三层到七层登录的华丽转身,开始很不知所措,三层实现之后一直忙着评教的维护工作,而且设计模式也好长时间没看了,直接实现七层不知道如何下手,就找了很多资料,看了很多大牛的博客,稀里糊涂照猫画虎,就敲完了,兴奋了一秒钟,试了试,根本传不到D层,就直接在U层抛错了,作为一名立志成为IT女超人的我是有这个心里准备的,怎么可能一次就成功呢,旅途一定是漫长且坎坷的,经过这两三天的调错经历,我感觉我对于调错的心态改变了很多:1.不能着急,越着急越理不清楚,简单的错也看不出来  2.要坚信,你一定能解决这个问题 。不说废话了,直接总结啦


七层构成



传统的七层是有七个“包”的,但是上边多了一个SQLHelper的包,许多童鞋把这个类放到了DAL层,也有的像我一样重新分出一层,这都是没有关系的,只要引用关系对了,这都是无关紧要的。和三层对比可以发现,UI和BLL层多了一个外观层,BLL和DAL层中间多了一个接口层,还多了一个工厂层。


设想原来的程序,UI层调用BLL层的方法,而BLL层调用DAL层的方法,如果被调用层代码被更改,那么势必影响到调用层的代码,这就违背了开闭原则,好的系统提倡对更改关闭,对拓展开放,所以三层中各更次之间的耦合性还是非常强的。七层就是降低了原来三层的耦合程度。外观层解耦UI层和BLL层,而工厂的引入是为了利用反射原理,通过添加配置文件,读取配置文件,方便更换数据库,接口类是使得BLL层和DAL层解耦


外观模式

定义:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

结合机房:外观这一层会去自动要要传递信息的类,而不是UI层直接去找,UI层直接接受一个外观层返回的结果就好,他甚至不需要知道BLL层中有哪些内容,他只认识外观一个小伙伴就够了。看下边这个示意图,更清楚明了一些



抽象工厂+反射


这里新添的工厂类和接口类使我们的系统在遇到变更数据库的时候,变得异常的便捷。如果不使用反射,那么就需要实例化DAL层的对象,而反射也可以指明需要实例的DAL层的对象。大家注意看下边类图中工厂类的属性中,DB是字符串,工厂类通过变量来实例化DAL层的对象,这样将程序由编译转化为运行时,而变量又是随时可以更换的,如果要更换数据库,在配置文件中更改相应的代码就能达到目的。




时序图

这里只写了在数据库中查找是否存在这个用户的时序图,判读密码是否正确的图和这个大同小异,就不列举了



代码

【实体层】

'**************************  '文 件 名:LoginEntity  '命名空间:Entity  '内    容:  '功    能:  '文件关系:  '作    者:陈丹  '小    组:陈丹  '生成日期:2015.12.21 15:30'版 本 号:V1.0.0.0  '修改日志:  '版权说明:  '*************************** Public Class LoginEntity#Region "定义变量"    Private _userid As String  '这个字段是为了方便在类内传值,所以是私有的    Private _password As String    Private _oldpassword As String    Private _userlevel As String    Private _head As String    Private _userstatus As String#End Region    '定义全局变量    Public Shared UserHead As String    Public Property UserID As String        Get            Return _userid        End Get        Set(value As String)            _userid = value        End Set    End Property    Public Property PassWord As String        Get            Return _password        End Get        Set(value As String)            _password = value        End Set    End Property    Public Property OldPassword As String        Get            Return _oldpassword        End Get        Set(value As String)            _oldpassword = value        End Set    End Property    Public Property UserLevel As String        Get            Return _userlevel        End Get        Set(value As String)            _userlevel = value        End Set    End Property    Public Property Head As String        Get            Return _head        End Get        Set(value As String)            _head = value        End Set    End Property    Public Property UserStatus As String        Get            Return _head        End Get        Set(value As String)            _head = value        End Set    End PropertyEnd Class


【SQLHelper】

'**************************  '文 件 名:sqlHelper  '命名空间:SQLHelper  '内    容:  '功    能:  '文件关系:  '作    者:陈丹  '小    组:陈丹  '生成日期:2015.12.21 19:18'版 本 号:V1.0.0.0  '修改日志:  '版权说明:  '***************************  Imports System.Data.SqlClientImports System.ConfigurationImports System.DataPublic Class sqlHelper    '配置文件    'Private ReadOnly strconnection As String = ConfigurationManager.AppSettings("strConnection")    Dim strConnection As String = "server=.;Database=JFroom;User ID=sa;PassWord=1;"    Dim conn As SqlConnection = New SqlConnection(strConnection)    Dim cmd As New SqlCommand 
#Region "查询,返回结果集"    ''' <summary>    ''' 执行查询操作,返回DATATABLE    ''' </summary>    ''' <param name="cmdText"></param>    ''' <param name="cmdType"></param>    ''' <param name="paras">传入参数</param>    ''' <returns></returns>返回DataTable    ''' <remarks></remarks>    Public Function ExecDataTable(ByVal cmdText As String, ByVal cmdType As CommandType, ByVal paras As SqlParameter()) As DataTable        Dim sqlAdapter As SqlDataAdapter        Dim dt As New DataTable        Dim ds As New DataSet        cmd.CommandText = cmdText        cmd.CommandType = cmdType        cmd.Connection = conn        cmd.Parameters.AddRange(paras) '参数添加        sqlAdapter = New SqlDataAdapter(cmd) '实例化adapter        Try            sqlAdapter.Fill(ds)            dt = ds.Tables(0)            cmd.Parameters.Clear()        Catch ex As Exception            MsgBox("登录失败")        Finally            Call CloseCmd(cmd)        End Try        Return dt    End Function#End Region

#Region "关闭命令,关闭连接"    Public Sub CloseCmd(ByVal cmd As SqlCommand)        If Not IsNothing(cmd) Then '判断是否为空            cmd.Dispose() '销毁            cmd = Nothing        End If    End Sub    Public Sub CloseConnection(ByVal conn As SqlConnection)        If Not IsNothing(conn.State <> ConnectionState.Closed) Then            conn.Close()            conn = Nothing        End If    End Sub#End RegionEnd Class

【UI】

Imports BLL.LoginBLLImports Entity.LoginEntityImports Facade.LoginFacadePublic Class LoginUI    Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click        If txtUserID.Text = "" Then            MsgBox("用户名不能为空!")            txtUserID.Focus()            Exit Sub        ElseIf txtPwd.Text = "" Then            MsgBox("密码不能为空!")            txtPwd.Text = ""            txtPwd.Focus()            Exit Sub        End If        Try            '定义一个外观层对象            Dim facadeLogin As New Facade.LoginFacade            Dim UserInfo As New Entity.LoginEntity()            '将文本框中的值传给实体层对象让他带上参数            UserInfo.UserID = txtUserID.Text            UserInfo.PassWord = txtPwd.Text            Dim strResult As Boolean            strResult = facadeLogin.CheckUser(UserInfo) '将U层文本框的内容传入外观层,然后通过外观层传入b层            If strResult = False Then                MsgBox("用户不存在!")                txtUserID.Text = ""                txtPwd.Text = ""                txtPwd.Select()                txtUserID.Focus()            End If            Dim table As DataTable            table = facadeLogin.CheckPWD(UserInfo)            If Trim(txtPwd.Text) = Trim(table.Rows(0).Item(1)) Then                MsgBox("登录成功!")                txtUserID.Text = ""                txtPwd.Text = ""            End If        Catch ex As Exception            MsgBox("用户不存在或密码不正确!")            txtUserID.Text = ""            txtPwd.Text = ""            txtUserID.Select() '选中控件中的文本            txtUserID.Focus()        End Try    End SubEnd Class


【Facade】


Imports BLLImports EntityPublic Class LoginFacade    Public Function CheckUser(ByVal UserInfo As Entity.LoginEntity) As Boolean        Dim isUserExists As New BLL.LoginBLL()        Dim flag As Boolean        flag = isUserExists.ExistUser(UserInfo)        If flag = True Then            Return True        Else            Return False        End If    End Function    Public Function CheckPWD(ByVal UserInfo As Entity.LoginEntity) As DataTable        Dim isPwdRight As New BLL.LoginBLL()        Dim table As DataTable        table = isPwdRight.RightPWD(UserInfo)        Return table    End FunctionEnd Clas


【BLL】

Imports IDALPublic Class LoginBLL    Public Function ExistUser(ByVal UserInfo As Entity.LoginEntity) As Boolean        Dim fa As New Factory.LoginFactory()        Dim Iuser As IDAL.ILoginDAL        '调用“创建用户”的工厂方法        Iuser = fa.CreateUserInfo        Dim table As DataTable        Dim flag As Boolean        table = Iuser.selectUser(UserInfo)        If table.Rows(0).Item(0) = 0 Then  '表中的第一行第一列            flag = False        Else            flag = True        End If        Return flag    End Function    Public Function RightPWD(ByVal UserInfo As Entity.LoginEntity) As DataTable        Dim fa As New Factory.LoginFactory()        Dim Iuser As IDAL.ILoginDAL        Dim dt As DataTable        Iuser = fa.CreateUserInfo        dt = Iuser.selectUser(UserInfo)        Return dt    End FunctionEnd Class


【Factory】

Imports System.Configuration '添加对配置文件的引用Imports System.Reflection  '添加对反射的引用Imports IDALPublic Class LoginFactory    Private Shared ReadOnly AssemblyName As String = "DAL"    'Private Shared db As String = ConfigurationManager.AppSettings("strConnection")    Dim db As String = System.Configuration.ConfigurationManager.AppSettings("DB")    Public Function CreateUserInfo() As ILoginDAL        'Dim className As String = AssemblyName + "." + db + "LoginDAL" 'DAL层的类名        Dim className As String = AssemblyName + "." + "LoginDAL" 'DAL层的类名        Dim iUser As ILoginDAL        iUser = CType(Assembly.Load(AssemblyName).CreateInstance(className), ILoginDAL) '通过接口去调用D层实现接口中的方法,返回的是接口的实例化对象        Return iUser        '这里略写了    End FunctionEnd Class


【IDAL】

'**************************  '文 件 名:ILoginDAL  '命名空间:IDAL '内    容:  '功    能:  '文件关系:  '作    者:陈丹  '小    组:陈丹  '生成日期:2015.12.21 19:18'版 本 号:V1.0.0.0  '修改日志:  '版权说明:  '***************************  Imports Entity.LoginEntityPublic Interface ILoginDAL    'UserInfo是实体实例化的对象,用来传值    '接口定义了一个查找用户的方法,用于在数据库中查找用户    Function selectUser(ByVal UserInfo As Entity.LoginEntity) As DataTableEnd Interface


【DAL】

'**************************  '文 件 名:sqlHelper  '命名空间:SQLHelper  '内    容:  '功    能:  '文件关系:  '作    者:陈丹  '小    组:陈丹  '生成日期:2015.12.22 10:11'版 本 号:V1.0.0.0  '修改日志:  '版权说明:  '*************************** Imports System.Data.SqlClient '命名空间Imports EntityImports IDAL'Imports System.ConfigurationImports SQLHelperPublic Class LoginDAL : Implements IDAL.ILoginDAL '实现接口中定义的方法    Public Function selectUser(UserInfo As LoginEntity) As DataTable Implements ILoginDAL.selectUser                Dim sqlhelper As New SQLHelper.sqlHelper        Dim cmdType As CommandType = New CommandType()        Dim paras As SqlParameter() = {New SqlParameter("@UserID", UserInfo.UserID), New SqlParameter("@password", UserInfo.PassWord)}        Dim cmdText As String        cmdText = "select * from User_Info where userID=@UserID and passWord=@password"        'cmdType = CommandType.StoredProcedure '定义命令方式为存储过程        Dim dt As New DataTable        dt = sqlhelper.ExecDataTable(cmdText, CommandType.Text, paras)        Return dt    End FunctionEnd Class


总结

我们总是惧怕一个看上去很困难的事情,于是拖延症就出现了,其实把大的目标划分成小目标,逐个击破,这件事情就会变得很简单,就像跑马拉松一样,在重构机房的这条道路上,给自己多设几个终点站,这是我的第二站七层登录实现,下一个小目标就是完成修改密码~加油,学习是一个过程,困难是必然会出现的,困难就是为了让我们能看到自己有什么不足的地方,做不到的地方不管是查资料还是请教别人,不管用什么方法,坚信这个困难是绝对可以解决的,不要想那么多就好了!!~~~ 登录磨叽了小一个星期,这条线在调错改错的过程中日渐清晰明朗,希望下个一个站点我可以快快的到达!~


2 0
原创粉丝点击