机房收费系统重构之用户登录

    机房收费系统开始了有一段时间了,但是感觉自己对于这一条线还是理解的不太深刻,导致后面也快不起来,所以来分析一下这用户登录的过程。

    如果是纯三层的话,理解起来差不多,无非就是在层与层之间传递,但是随着用户需求,软件功能越来越多,那么其复杂程度越来越大。


   因此,我们引入了更多层,从图中看,我们觉得好像这样比三层更加复杂,但是实现过程中我们会体现其高内聚,低耦合的优点。我们不难发现这是从三层加入设计模式演化而来,之所以采用抽象工厂模式是考虑到换数据库的方便,而应用外观模式是为了解决UI层和BLL层耦合性过高的问题,而UI层不用知道BLL层的存在,而Facade知道BLL层哪些类负责哪些请求,将UI层的请求代理给适当的BLL层的类。

一、抽象类

    整体有了,接下来就是细节了,也就是从宏观到微观。

1.抽象实体类

第一步要做的就是抽象实体层的类(Entity),因为信息系统是对数据的操作和处理,首先

必须要有数据,这个时候,我们要返回需求,了解用户的数据要求,以此为依据进行数据库设计。

在这里我们就需要抽象出UserEntity类。

<span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class UserEntity
    Private _userName As String
    Private _PWD As String
    Private _userLevel As String
    Private _accounter As String
    Public Shared UserHead As String
    Public Property userName() As String
        Get
            Return _userName
        End Get
        Set(value As String)
            _userName = value
        End Set
    End Property
    Public Property PWD() As String
        Get
            Return _PWD
        End Get
        Set(value As String)
            _PWD = 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 accounter() As String
        Get
            Return _accounter
        End Get
        Set(value As String)
            _accounter = value
        End Set
    End Property
End Class</span>

2.UI层
U层负责数据的输入与输出,首先对输入的数据要求进行判定,符合要求之后调用外观的验证用户和密码的方法。

<span style="font-family:KaiTi_GB2312;font-size:18px;">Imports BLL
Imports Entity
Public Class frmLoginUI
    Private Sub btOK_Click(sender As Object, e As EventArgs) Handles btOK.Click
        Dim enUser As New Entity.UserEntity
        'Dim loginFA As Facade.loginFacade         '实例化过程
        enUser.userName = txtUser.Text.Trim            '赋值过程
        enUser.PWD = txtPWD.Text.Trim

        'Dim strResult As String
        '判断是否输入了用户名及密码
        If txtUser.Text.Trim() = "" Then
            MessageBox.Show("请输入用户ID", "", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            txtUser.Select()
            txtUser.Focus()
            Exit Sub
        ElseIf IsNumeric(txtUser.Text) = False Then
            MsgBox("用户名请输入数字")
            txtUser.Text = ""
            txtUser.Select()
            txtUser.Focus()
            Exit Sub
        ElseIf txtPWD.Text.Trim() = "" Then
            MessageBox.Show("请输入密码", "", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            txtPWD.Select()
            txtPWD.Focus()
            Exit Sub
        End If

        'Try
        '定义一个外观层的对象
        Dim FacadeLogin As New Facade.loginFacade

        Dim strResult1 As Boolean
        strResult1 = FacadeLogin.CheckUser(enUser)
        If strResult1 = False Then
            MsgBox("用户不存在")
            txtUser.Text = ""
            txtUser.Select()
            txtUser.Focus()
        End If

        Dim table As DataTable
        table = FacadeLogin.CheckPwd(enUser)
        If Trim(txtPWD.Text) = Trim(table.Rows(0).Item(1)) Then
            MsgBox("登陆成功")
            Me.Hide()
            frmMainUI.Show()
        Else
            MsgBox("密码不正确")
            txtPWD.Text = ""
            txtPWD.Select()
            txtPWD.Focus()
        End If
    End Sub

    Private Sub btCancel_Click(sender As Object, e As EventArgs) Handles btCancel.Click
        End

    End Sub

    Private Sub frmLoginUI_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        txtUser.Select()
        txtUser.Focus()
    End Sub
End Class</span>

3.外观层

外观其实就是方法的封装,而对于外观层在登陆的时候其实作用不大,但同样调用B层方法。

<span style="font-family:KaiTi_GB2312;font-size:18px;">Imports BLL
Public Class loginFacade
    Public Function CheckUser(ByVal enUser As Entity.UserEntity) As Boolean
        '用于检查用户是否存在
        Dim IsUserExistsBLL As New BLL.IsExists
        Dim flag As Boolean
        flag = IsUserExistsBLL.IsUserExists(enUser)
        If flag = True Then
            Return True
        Else
            Return False
        End If
    End Function
    '检查用户是否正确
    Public Function CheckPwd(ByVal enUser As Entity.UserEntity) As DataTable
        Dim IsPwdBLL As New BLL.IsExists
        Dim table As DataTable
        table = IsPwdBLL.CheckUserPWD(enUser)
        Return table
    End Function
End Class</span>

4.BLL层
验证用户是否存在和密码是否正确,验证方法通过工厂和IDAL接口进行,首先实例化工厂,然后定义接口变量,调用工厂中的方法,然后对返回数据进行的逻辑判断

<span style="font-family:KaiTi_GB2312;font-size:18px;">Imports IDAL
Imports Entity
Public Class IsExists
    '检查用户是否存在
    Public Function IsUserExists(ByVal enUser As Entity.UserEntity) As Boolean
        '定义并实例化一个工厂
        Dim factory As New Factory.DataAccess
        '定义一个接口变量
        Dim IUser As IUser
        '通过调用创建用户的工厂方法
        IUser = factory.CreateUser
        Dim table As DataTable
        Dim flag As Boolean
        table = IUser.CheckExistsUser(enUser)
        If table.Rows.Count = 0 Then
            flag = False
        Else
            flag = True
        End If
        Return flag
    End Function
    '查密码是否正确
    Public Function CheckUserPWD(ByVal enUser As UserEntity) As DataTable
        Dim factory As New Factory.DataAccess  '定义工厂并实例化工厂变量factory
        Dim IUser As IUser  '定义接口变量IUser
        Dim table As DataTable   '中间变量,用于存储D层查询到的数据
        IUser = factory.CreateUser   '调用工厂的CreateUser方法创建iuser接口实例
        table = IUser.CheckExistsUser(enUser)  '调用接口的方法UserIsExist,并将返回值返回给flag

        Return table
    End Function
End Class</span>

5.工厂类  

经典的工厂层的设计,用反射+配置文件,防止更换数据库。

<span style="font-family:KaiTi_GB2312;font-size:18px;">Imports System.Reflection
Imports System.Configuration
Imports IDAL

'/****************************************************************************
'类 名 称:SqlServerFactory
'命名空间:Factory
'内    容:读配置文件来给DB字符串赋值,在配置文件中写明是SqlServer还是Access,想要更换数据
'库直接改配置文件就行。前提是:Sqlserver前缀的DAL层类里写的是访问SQLServer数据库的代码。
'Access前缀的DAL层类里写的是访问Access数据库的代码。
'功    能:用反射+配置文件+抽象工厂,方便更换数据库
'创建时间:2014/8/14 10:40:59
'作    者:王金博
'修改时间:
'修 改 人:
'版 本 号:v1.0.0
'****************************************************************************/
Public Class DataAccess
    '利用反射+配置文件+抽象工厂
    Private Shared ReadOnly AssemblyName As String = "DAL"
    '定义程序集名称变量,D层命名空间的名字
    Private Shared ReadOnly db As String = ConfigurationManager.AppSettings("DB")
    '表示读配置文件,如果配置文件中是Sqlserver,就访问SQLServer数据库,如果是别的就访问别的,不用更改程序中的代码。

    '创建用户表的工厂
    Public Function CreateUser() As IUser
        Dim className As String = AssemblyName + "." + db + "UserDAL"
        'AssemblyName是程序集的名称,db+"UserDAL"是DAL层中的SqlServerUserDAL。如果不用SqlServer数据库,那么我在
        'Factory中再另建一个类,比如访问Access数据库,那么类名就叫AccessUserDAL。把配置文件中Value 值改为
        'Access。这样就是扩展而不是修改。
        Dim iuser As IUser
        iuser = CType(Assembly.Load(AssemblyName).CreateInstance(className), IUser)
        '将实例化的D层通过向上转型转换成接口类,然后通过调用接口类中的函数来调用D层中实现该接口的函数
        Return iuser
    End Function
End Class</span>

6.接口层

定义一个用于解耦B层和D层的接口

<span style="font-family:KaiTi_GB2312;font-size:18px;">Public Interface IUser
    '检查用户是否存在和密码是否正确
    Function CheckExistsUser(ByVal enUser As Entity.UserEntity) As DataTable
End Interface</span>

7.DAL层

用于连接数据库,实现接口

<span style="font-family:KaiTi_GB2312;font-size:18px;">Imports Entity
Imports IDAL
Imports System.Data.SqlClient
Public Class SqlserverUserDAL : Implements IUser

    Public Function SelectExistsUser(enUser As UserEntity) As DataTable Implements IUser.CheckExistsUser
        Dim sql As String  '定义字符串变量sql,用于存放要执行的sql语句
        Dim table As DataTable '定义表变量table,用于存储执行的结果并返回
        Dim paras As SqlParameter() = {New SqlParameter("@userName", enUser.userName), New SqlParameter("@PWD", enUser.PWD)}

        sql = "select * from T_User where userName=@UserName and PWD=@PWD"  '存储sql语句
        table = SqlHelper.SqlHelper.GetDataTable(sql, CommandType.Text, paras) '执行sql语句,将结果赋给table
        Return table
    End Function
End Class
</span>
总之,我们尽量做到符合单一职责原则,一个类完成一个功能,高内聚,低耦合,使得每层之间联系变得很少,而使用设计模式让我们的思路更加清晰,能够让系统更好地去扩展以及维护。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 62
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 62
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值