重构个人版机房收费系统——外观模式

时间:2022-12-20 15:20:18

       个人版机房重构正式开始有一段时间了,之前一直都是在用C#敲三层,刚开始转到.NET还有点不顺手呢,等敲了两条线感觉好多了。通过这次机房重构要在三层的基础上要加强对之前学习的设计模式的应用和练习,也算是学以致用了~~其中要用到抽象工厂、外观、模板等设计模式。今天主要来学习外观模式的应用。

 

        要想应用外观模式之前,首先,我们先来了解一下什么是外观模式,它有什么好处,到底该怎么用?

 

        外观模式,为子系统中的一组接口提供一个一致的界面。说白了就是用一个类将需要用到的多个子系统中的方法或属性封装到一起供外界使用,降低程序的耦合度。

 

        例如,用户登录功能,用户登录时系统要先判断用户信息是否正确,如果正确那么需要在工作日志表中同时添加一条工作记录。而用户只是想登录并使用程序,根本不需要知道这些操作,这时我们就可以定义一个外观类:登录,将判断用户信息和添加工作日志的操作封装到一起,用户只根据发送的登录请求返回的信息进行相应的操作就可以了。如果还需要添加其他功能,同样的我们只需要在外观类中多封装一个方法就可以了,不用改变登录窗体。

 

       再例如,充值功能,给一张卡充值,系统要先判断卡号是否已经注册,如果卡号确实存在,然后要更新卡的余额信息,同时还要在充值表中添加一条充值记录,用到了”增、改、查”三个操作,而用户对这些是不感兴趣的,他们只需要知道最后的结果就可以了,所以我们就可以用一个充值的外观类来封装所有的方法,所有的操作都在后台默默地执行最后返给用户一条结果就可以了。

 

       好了,文字介绍了外观的功能,接下来我们看一下简单的代码实现吧~~以登录窗体来举例好了。。。


实体层:Entiry


一个实体类对应一张表,用户实体类如下,工作日志实体类同理,不再重复

<span style="font-size:18px;">Public Class En_UserInfo
Private Shared _userID As Integer
Public Shared _userName As String
Public Shared _userLevel As String
Public Shared _password As String
Public Shared _head As Integer

''' <summary>
''' 设置和获得用户ID值
''' </summary>
''' <value>用户ID</value>
''' <returns>用户ID</returns>
''' <remarks></remarks>
Public Property UserID() As Integer
Get
Return _userID
End Get
Set(value As Integer)
_userID = value
End Set
End Property

Public Property UserName() As String
Get
Return _userName
End Get
Set(value As String)
_userName = 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 PassWord() As String
Get
Return _password
End Get
Set(value As String)
_password = value
End Set
End Property
Public Property Head() As Integer
Get
Return _head
End Get
Set(value As Integer)
_head = value
End Set
End Property
End Class</span>

D层:


从用户表中查询用户信息判断输入的信息是否正确

<span style="font-size:18px;"><span style="font-size:18px;">Imports System.Data
Imports System.Data.SqlClient
Imports Entity
Imports SqlHelper
Imports IDAL

Public Class UserDAO : Implements IDAL.IUserInfo
Dim dt As New DataTable
Dim sqlhelper As New Global.SqlHelper.SqlHelper
Dim flag As Boolean

''' <summary>
''' 根据ID号得到用户信息
''' </summary>
''' <param name="user"></param>
''' <returns>datatable</returns>
''' <remarks></remarks>
Public Function GetUserInfo(ByVal user As En_UserInfo) As DataTable Implements IUserInfo.GetUserInfo
Dim sql As String = "select * from user_table where userID=@UserID" '查询语句
Dim paras As SqlParameter() = {New SqlParameter("@UserID", user.UserID)}
'添加参数
dt = sqlhelper.ExecSelect(sql, CommandType.Text, paras)
Return dt
End Function</span></span>


往工作日志表中添加一条工作记录

<span style="font-size:18px;"><span style="font-size:18px;">Imports Entity
Imports SqlHelper
Imports IDAL
Imports System.Data
Imports System.Data.SqlClient
Public Class WorkLogDAO : Implements IDAL.IWorkLogInfo
Dim sqlhelper As New SqlHelper.SqlHelper
Dim flag As Boolean
Dim dt As New DataTable
Dim sql As String
Dim paras As SqlParameter()
''' <summary>
''' 添加工作日志记录
''' </summary>
''' <param name="enworklog"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function AddWorkLog(enworklog As En_WorkInfo) As Object Implements IWorkLogInfo.AddWorkLog

sql = "insert into worklog_table (userID,onDate,onTime,computerID) values (@userID,@onDate,@onTime,@compuerID)"
paras = {New SqlParameter("@userID", enworklog.userID),
New SqlParameter("@onDate", enworklog.onDate),
New SqlParameter("@onTime", enworklog.onTime),
New SqlParameter("@compuerID", enworklog.compuerID)}
flag = sqlhelper.ExecAddDelUpdate(sql, CommandType.Text, paras)
Return flag
End Function</span></span>

B层


此处将外观层定义为一个类添加到了B层,定义外观类为F_Login。当然可以根据自己的需要,也可以把外观层以新项目的形式添加到总项目根目录下

<span style="font-size:18px;"><span style="font-size:18px;">Imports Entity
Public Class F_Login '相当于外观模式中的"基金"类
Public bUserInfo As New UserBLL
Public bWorkLog As New WorkLogBLL
''' <summary>
''' 相当于外观模式中基金的"买/卖"方法
''' </summary>
''' <param name="enuser"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function Login(ByVal enuser As En_UserInfo, ByVal enworklog As En_WorkInfo) As String
Dim result As String
Dim dt As New DataTable
Try
result = bUserInfo.VerifyPassWord(enuser)
Catch ex As Exception
MsgBox(ex.Message, vbOKOnly, "提示信息")
End Try

If result = "用户成功登陆" Then
Try
bWorkLog.AddWorkLog(enworklog)
Catch ex As Exception
MsgBox(ex.Message, vbOKOnly, "提示信息")
End Try
End If
Return result
End Function
End Class
</span></span>

以下两段代码相当于子系统中的方法实现


<span style="font-size:18px;"><span style="font-size:18px;">Imports System.Data
Imports System.Data.SqlClient
Imports Entity
Imports chargeDAL
Imports IDAL
Imports SqlFactory.sqlFactory
Public Class UserBLL
'创建工厂类,来创建接口对象
Public userfactory As New SqlFactory.sqlFactory
Dim dt As New DataTable

''' <summary>
''' 判断用户是否已经存在
''' </summary>
''' <param name="user"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function IsExist(ByVal user As En_UserInfo) As Boolean
Dim Iselectuser As IDAL.IUserInfo
Iselectuser = SqlFactory.sqlFactory.GetUserInfo
Try
dt = Iselectuser.GetUserInfo(user)
Catch ex As Exception
MsgBox(ex.Message, vbOKOnly, "提示信息")
End Try

If dt.Rows.Count > 0 Then
'MsgBox("用户已经注册,不能重复注册")
Return False '用户已经存在
Else
Return True
End If
End Function

''' <summary>
''' 判断用户密码是否正确
''' </summary>
''' <param name="enuser"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function VerifyPassWord(ByVal enuser As En_UserInfo) As String
'创建获得用户信息的接口
Dim flag As String
Dim IGetPwd As IDAL.IUserInfo
Dim Iwork As IDAL.IWorkLogInfo

IGetPwd = SqlFactory.sqlFactory.GetUserInfo
dt = IGetPwd.GetUserInfo(enuser)
If dt.Rows.Count = 0 Then '用户不存在
flag = "该用户不存在!"
Return flag
Else
If enuser.PassWord = Trim(dt.Rows(0).Item(2)) Then
flag = "用户成功登陆" '密码正确
Iwork = SqlFactory.sqlFactory.GetWorkInfo
Else
flag = "密码错误,请重新输入!"
End If
Return flag
End If

End Function</span></span>
***********************************************************************************************************************************************************************************************************************************************************************
<span style="font-size:18px;"><span style="font-size:18px;">Imports Entity
Imports SqlFactory
Imports IDAL
Public Class WorkLogBLL
''' <summary>
''' 添加工作日志
''' </summary>
''' <param name="enwork"></param>
''' <remarks></remarks>
Public Sub AddWorkLog(ByVal enwork As En_WorkInfo)
Dim Iaddworklog As IDAL.IWorkLogInfo
Try
Iaddworklog = SqlFactory.sqlFactory.GetWorkInfo
Iaddworklog.AddWorkLog(enwork)
Catch ex As Exception
MsgBox(ex.Message, vbOKOnly, "提示信息")
End Try
End Sub
End Class</span></span>


U层:


<span style="font-size:18px;"><span style="font-size:18px;">Imports chargeManageBLL
Imports Entity
Public Class frmLogin
''' <summary>
''' 确定登录
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles btnOK.Click
Dim blogin As New F_Login
Dim enuser As New En_UserInfo '定义实体变量
Dim result As String '定义一个标识
Dim enworklog As New En_WorkInfo

enuser.UserID = txtUserID.Text.Trim()
enuser.PassWord = txtPwd.Text.Trim()

enworklog.userID = txtUserID.Text
enworklog.onDate = DateTime.Today.ToString("yyyy-MM-dd")
enworklog.onTime = DateTime.Now.ToString("HH:mm")
enworklog.compuerID = Environment.MachineName
'enworklog.offTime = "null"
'enworklog.offDate = "null"

Try
result = blogin.Login(enuser, enworklog)
Catch ex As Exception
MsgBox(ex.Message, vbOKOnly, "提示信息")
End Try

If result = "用户成功登陆" Then
frmMain.Show()
Else
txtUserID.Text = ""
txtPwd.Text = ""
txtUserID.SelectAll()
txtUserID.Focus()
End If
End Sub</span></span>

       刚开始的时候,每个功能都添加了外观模式,比如查询充值记录、添加充值记录等等,呵呵~~~~后来跟师父交流,其实并不是每个功能都需要用到外观模式的,例如上面提到的添加充值记录,本来就是一个简单的功能,如果在加上外观模式其实就起反作用了,一两个还好,要是整个程序下来反而事倍功半,增加了程序的复杂度,在程序实现过程中确实有这种体会。所以说东西好也不可以无节制、无选择的使用。


编程在继续,经验在积累,如有不同看法或者更好的理解欢迎来交流~~~~