机房重构从登陆开始,由三层框架转向七层非常的不容易,代码一点一点敲上去然后生成解决方案后一层一层地抛错,什么问题都有,好在慢慢都解决了,虽然有的问题自己都不知道怎么就解决了,但是管他呢,慢慢来吧~
七层框架相比三层,不过是多了外观层(Facade)、工厂层(Factory)和接口层(IDAL),设计模式的应用大大降低了三层架构间的耦合度。七层之间的关系如下:
下面看一下加入设计模式后的七层架构是怎样的:
UI层
U层不再和B层直接交互,而是和外观层进行交互,将用户信息从外观层导入B层进行信息处理,这样在对U层或B层改动时减少互相影响,更好地接触耦合度。
Public Class frmLogin Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click '输入不能为空 If txtUserName.Text = "" Then MsgBox("请输入用户名", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) txtUserName.Focus() End If If IsNumeric(txtUserName.Text) = False Then MsgBox("用户名请输入数字", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) txtUserName.Text = "" End If If txtPassword.Text = "" Then MsgBox("请输入密码", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) txtPassword.Focus() End If Try Dim Facade As New Facade.LoginFacade Dim UserInfo As New Model.LoginUserInfo UserInfo.UserName = txtUserName.Text.Trim UserInfo.Password = txtPassword.Text Dim strResult As Boolean '将U层的用户信息传入外观层,然后通过外观层传入B层进行判断 strResult = Facade.CheckUser(UserInfo) If strResult = False Then MsgBox("用户不存在", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) txtUserName.Text = "" txtPassword.Text = "" txtUserName.Select() txtUserName.Focus() End If Dim table As DataTable table = Facade.CheckPwd(UserInfo) If Trim(txtPassword.Text) = Trim(table.Rows(0).Item(2)) Then MsgBox("登陆成功!") Me.Hide() txtPassword.Text = "" txtUserName.Text = "" End If Catch ex As Exception MsgBox("用户不存在或密码不正确") txtPassword.Text = "" txtUserName.Text = "" txtUserName.Select() txtUserName.Focus() End Try End Sub End ClassFacade层
外观层主要是对方法的封装,但还是调用的B层的方法,不过让数据在外观层走一遍。
Public Class LoginFacade '检查用户是否存在 Public Function CheckUser(ByVal UserInfo As Model.LoginUserInfo) As Boolean Dim IsUserExists As New BLL.LoginBLL Dim flag As Boolean flag = IsUserExists.Checkuser(UserInfo) If flag = True Then Return True Else Return False End If End Function '检查密码是否正确 Public Function CheckPwd(ByVal UserInfo As Model.LoginUserInfo) As DataTable Dim IsPwdExists As New BLL.LoginBLL Dim table As DataTable table = IsPwdExists.Checkpwd(UserInfo) Return table End Function End ClassBLL层
B层进行数据的逻辑处理,返回给外观层处理的信息进行判断,另一方面是接收通过工厂和接口后传来的D层的信息。
Imports IDAL Public Class LoginBLL Public Function Checkuser(ByVal UserInfo As Model.LoginUserInfo) As Boolean Dim Factory As New Factory.LoginFactory Dim IUser As IDAL.LoginIUserInfo '调用创建用户的工厂方法 IUser = Factory.CreateIUser() '调用工厂的CreatIUser方法创建Iuser接口实例 Dim table As New DataTable Dim flag As Boolean table = IUser.selectUser(UserInfo) If table.Rows.Count = 0 Then flag = False Else flag = True End If Return flag End Function Public Function Checkpwd(ByVal UserInfo As Model.LoginUserInfo) As DataTable Dim Factory As New Factory.LoginFactory Dim IUser As IDAL.LoginIUserInfo Dim table As DataTable IUser = Factory.CreateIUser table = IUser.selectUser(UserInfo) Return table End Function End ClassFactory层
通过读取配置文件,在以后更换数据库的时候,只需要增加一个新的类,而不需要修改原来的代码。
Imports System.Reflection '添加对反射的引用 Imports System.Configuration '添加对配置文件的引用 Imports System.Data Imports IDAL '引用接口层 '反射+配置文件+抽象工厂实现数据访问 Public Class LoginFactory Private Shared ReadOnly AssemblyName As String = "DAL" '数据程序集名称&命名空间DAL Dim strDB As String = System.Configuration.ConfigurationSettings.AppSettings("DB") Public Function CreateIUser() As LoginIUserInfo Dim classname As String = "DAL" + "." + strDB + "LoginDAL" '要实例化的D层的类的名称 Dim IUser As LoginIUserInfo 'CType函数将返回表达式显示地转换为指定的数据类型、对象、结构、类或接口后的结果 IUser = CType(Assembly.Load(AssemblyName).CreateInstance(classname), LoginIUserInfo) '返回LoginIUserInfo Return IUser End Function End ClassIDAL层
接口层用来定义一个统一的接口,解除B层和D层的耦合。
Public Interface LoginIUserInfo '判断用户名是否存在 Function selectUser(ByVal UserInfo As Model.LoginUserInfo) As DataTable End InterfaceDAL层
D层用实现接口的方法来实现用户对数据库进行增删改查的操作,与数据库打交道。
Public Class LoginDAL : Implements IDAL.LoginIUserInfo '实现接口中的方法 Private sqlHelper As New SqlHelper.sqlhelper '判断用户名是否存在 Public Function selectUser(UserInfo As LoginUserInfo) As DataTable Implements LoginIUserInfo.selectUser Dim sql As String '中间变量,用于储存从数据库中查找到的信息 Dim table As DataTable '声明一个Dat '声明并实例化参数数组 Dim sqlParams As SqlParameter() = {New SqlParameter("@UserName", UserInfo.UserName), New SqlParameter("@Password", UserInfo.Password)} sql = "select * from User_info where UserName=@UserName and Password=@Password" '调用SqlHelper类中的GetDataTable()方法来执行查询,并获取返回值 table = sqlHelper.ExecSelect(sql, CommandType.Text, sqlParams) Return table End Function End ClassEntity层
定义一个实体来封装数据,用以传输。
Private _username As String Public Property UserName As String Get Return _username End Get Set(value As String) _username = value End Set End Property Private _password As String Public Property Password As String Get Return _password End Get Set(value As String) _password = value End Set End Property End ClassSqlHelper层
封装好的增删改查数据库的类。
Imports System.Data Imports System.Data.SqlClient Imports System.Configuration Public Class sqlhelper '配置文件 'Private ReadOnly strConnection As String = ConfigurationSettings.AppSettings("ConnStr") '数据库连接 Dim strConnection As String = "Server=DESKTOP-5KMOCVI;Database=chargejf;User ID=sa;Password=123" Dim conn As New SqlConnection(strConnection) Dim cmd As New SqlCommand Public Function ExecSelect(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赋值 cmd.CommandText = cmdText cmd.CommandType = cmdType cmd.Connection = conn cmd.Parameters.AddRange(paras) '参数添加 sqlAdapter = New SqlDataAdapter(cmd) '实例化Adapter Try sqlAdapter.Fill(ds) '用adapter将dataset填充 dt = ds.Tables(0) 'datatable为dataSet的第一个表 cmd.Parameters.Clear() '清除参数 Catch ex As Exception MsgBox("数据库操作") Finally Call CloseCmd(cmd) '销毁cmd命令 End Try Return dt End Function Public Sub CloseCmd(ByVal cmd As SqlCommand) If Not IsNothing(cmd) Then '如果cmd命令存在 cmd.Dispose() '销毁 cmd = Nothing End If End Sub End Class
生成的代码图,和包图差不多,看来代码的大致流程和各层的调用是没错了。
七层登陆仅仅是个开始,把思路好好梳理清楚,机房重构才不会觉得那么难。加油吧,少年!!