引言
前两遍文章中,小编重点介绍了三层架构技术,我们已经了解到三层分为UI层、BLL层和DAL层。面向对象系统的设计与分析实际上就是追求的两点:一是高内聚,一是低耦合。这也是我们软件设计所要追求的,在三层的基础上继续解耦,从而引出今天咱们所要学习的主题——七层。
介绍
- 哪七层?
图1七层结构图
- 为什么要用七层?
从上图来看,数据的调用显得繁琐而抽象,也许这时候就会有人说,我只是想实现界面上与用户交互,然后根据用户的请求将数据读出/写入数据库就好了,为什么要做如此复杂的分层调用呢?从这个问句中我们也只看到了界面和数据库,也就是说从用户的需求来说,就是这两层而已,但是这里我们首先要搞清楚的是三层架构它主要是为程序员为了实现部署、开发、维护企业级数据库系统而服务的。如果我们在中间层实现了对表示层和数据库层的完全脱离,其部署、开发、维护系统的费用和时间至少降低到原来的一半,甚至更多。
- 如何实现呢?
图2 七层包图
- 系统通过应用程序客户端提供与用户的交互平台,并向服务器提交请求(界面外观层);
- 用户提交请求后,界面规则层对用户的数据按照业务逻辑层要求的接口参数封装规则封装用户数据,然后调用业务接口层对外提供的相应命令接口(界面规则层),
- 业务接口层通过对数据进行解析并分别送入不同的逻辑处理并向用户返回处理结果(业务接口层);
- 对于数据和命令的不同,处理方式也不同,我们将不同的处理方式都归类,并将接口层传入的数据及命令流入对应处理流程(业务规则层);
- 这时,不同的处理流程分析数据和命令产生出对应的一个实体,这个实体根据其本身的属性和方法以及上层传入的命令,将数据处理为数据访问层需要的接口参数,并向数据访问层提交访问数据库的请求,并向业务接口层返回访问结果(实体层);
- 数据访问层会将数据转化为数据库可识别的语句(SQL),并访问数据库层,访问结果会返回给实体层(数据访问层);
- 数据库层处理上层传入的SQL,读写数据库内置对象,并根据其内置对象本身的关系对数据做进一步校验和处理(数据库层)。
- 实现步骤
- 创建Entity,实现业务实体。
- 创建IDAL,实现接口。
- 创建DAL,实现接口里的方法。
- 增加UI.config里的配置信息,为DAL的程序集。
- 创建Factory,返回程序集的指定类的实例。
- 创建BLL,调用DALFactory,得到程序集指定类的实例,完成数据操作方法。
- 创建UI,调用BLL里的数据操作方法。
实习
- Entity层
Public Class UserEntity
'定义私有属性
Private _UserID As String
Private _Password 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 Class WorklogEntity
Private _UserID As String
Private _loginDateTime As String
Private _logoutDateTime As String
Private _Computer As String
Private _Level As String
Public Shared Property login_DateTime As String
Public Property UserID() As String
Get
Return _UserID
End Get
Set(value As String)
_UserID = value
End Set
End Property
Public Property loginDateTime() As String
Get
Return _loginDateTime
End Get
Set(value As String)
_loginDateTime = value
End Set
End Property
Public Property logoutDateTime() As String
Get
Return _logoutDateTime
End Get
Set(value As String)
_logoutDateTime = value
End Set
End Property
Public Property Computer() As String
Get
Return _Computer
End Get
Set(value As String)
_Computer = value
End Set
End Property
Public Property Level() As String
Get
Return _Level
End Get
Set(value As String)
_Level = value
End Set
End Property
End Class
- IDAL层
Public Interface IUser Function IDALUser(ByVal User As Entity.UserEntity) As DataTable End Interface
Public Interface IWorklog Function SaveWorklog(ByVal worklog As Entity.WorklogEntity) As Boolean End Interface
- DAL层
'********************************************** '文 件 名:LoginDAL '命名空间:DAL '内 容: '功 能: '文件关系: '作 者:杨倩 '小 组: '生成日期:2016/3/11 16:06:11 '版 本号:V1.0.0.0 '修改日志: '版权说明: '********************************************** Imports System.Data.SqlClient Imports IDAL Public Class LoginDAL : Implements IDAL.IUser '实现接口中的方法 Public Function IDALUser(User As Entity.UserEntity) As DataTable Implements IDAL.IUser.IDALUser Dim SqlParams As SqlParameter() = {New SqlParameter("@UserID", User.UserID), New SqlParameter("@passWord", User.Password)} Dim Sql As String = "select * from User_Info where userID=@userID and passWord=@passWord" 'Dim cmdText As String = "pro_selectUser" Dim SqlHelperObject As New SqlHelper.LoginSqlHelper '声明并实例化参数数组,将user.userID赋值给username,user.password赋值给password Dim cmdType As CommandType = New CommandType() Dim table As New DataTable '定义数据库表table作为中间变量 table = SqlHelperObject.Execute(Sql, cmdType, SqlParams) Return table '返回值 End Function End Class
'********************************************** '文 件 名:WorklogDAL '命名空间:DAL '内 容: '功 能: '文件关系: '作 者:杨倩 '小 组: '生成日期:2016/3/21 9:46:39 '版 本号:V1.0.0.0 '修改日志: '版权说明: '********************************************** Imports System.Data.SqlClient Imports IDAL Public Class WorklogDAL : Implements IDAL.IWorklog Public Function SaveWorklog(worklog As Entity.WorklogEntity) As Boolean Implements IDAL.IWorklog.SaveWorklog Dim Sql As String = "INSERT INTO Worklog_Info (UserID,loginDateTime,Computer) VALUES (@UserID,@loginDateTime,@Computer)" Dim SqlParams As SqlParameter() = {New SqlParameter("@UserID", worklog.UserID), New SqlParameter("@loginDateTime", worklog.loginDateTime), New SqlParameter("@Computer", worklog.Computer)} Dim cmdType As CommandType = CommandType.Text Dim SqlHelperObject As New SqlHelper.LoginSqlHelper Return SqlHelperObject.ExecuteQuery(Sql, cmdType, SqlParams) End Function End Class
- SQLHelper
''' <summary> ''' 执行查询的操作,(有参),参数不限 ''' </summary> ''' <param name="cmdText">需要执行语句,一般是Sql语句,也有存储过程</param> ''' <param name="cmdType">判断Sql语句的类型,一般都不是存储过程</param> ''' <param name="paras">传入的参数</param> ''' <returns></returns> ''' <remarks></remarks> Public Function Execute(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适配器 sqlAdapter.Fill(ds) '用adapter将dataSet填充 dt = ds.Tables(0) 'datatable为dataSet的第一个表 cmd.Parameters.Clear() '清除参数 'MsgBox("查询失败", CType(vbOKOnly + MsgBoxStyle.Exclamation, MsgBoxStyle), "警告") '最后一定要销毁cmd Call CloseConnection(conn) Call CloseCmd(cmd) Return dt End Function
''' <summary> ''' 执行增删改三个操作,(有参)返回值为boolean类型,确认是否执行成功 ''' </summary> ''' <param name="strText">需要执行语句,一般是sql语句,也有存储过程</param> ''' <param name="cmdType">判断SQL语句的类型,一般都不是存储过程</param> ''' <param name="sqlParams">参数数组,无法确认有多少参数</param> ''' <returns></returns> ''' <remarks></remarks> Public Function ExecuteQuery(ByVal strText As String, ByVal cmdType As CommandType, ByVal sqlParams As SqlParameter()) As Boolean cmd.CommandText = strText '命令文本 cmd.CommandType = cmdType '命令类型是存储过程 cmd.Connection = conn '连接数据库 '读取数据库中的表 cmd.Parameters.AddRange(sqlParams) '传参 Dim flag As Boolean = False conn.Open() flag = cmd.ExecuteNonQuery cmd.Parameters.Clear() Call CloseConnection(conn) Call CloseCmd(cmd) Return flag End Function
- Factory层
'********************************************** '文 件 名:LoginFactory '命名空间:Factory '内 容: '功 能: '文件关系: '作 者:杨倩 '小 组: '生成日期:2016/3/10 20:55:32 '版 本号:V1.0.0.0 '修改日志: '版权说明: '********************************************** Imports System.Reflection Imports IDAL Imports System.Data Imports System.Configuration Public Class LoginFactory '读配置文件,D层的每个类在配置文件里面对应一个key '把key变成变量,然后在下面这个方法中用这个变量就可以应用D层里面这个类了 Dim strDB As String = System.Configuration.ConfigurationSettings.AppSettings("DBString") Dim strQueryWorkLog As String = System.Configuration.ConfigurationSettings.AppSettings("DBStrQueryWorkLog") Public Function CreateUser() As IDAL.IUser 'CType:内联函数,将前面的部分转换成后面的部分 Return CType(Assembly.Load("DAL").CreateInstance("DAL.LoginDAL"), IDAL.IUser) End Function Public Function SaveWorkLog() As IDAL.IWorklog Return CType(Assembly.Load("DAL").CreateInstance("DAL.WorklogDAL"), IDAL.IWorklog) End Function End Class
- BLL层
'********************************************** '文 件 名:UserBLL '命名空间:BLL '内 容: '功 能: '文件关系: '作 者:杨倩 '小 组: '生成日期:2016/3/10 20:17:21 '版 本号:V1.0.0.0 '修改日志: '版权说明: '********************************************** Imports IDAL Public Class UserBLL '检查用户名是否存在 Public Function BLLUser(ByVal User As Entity.UserEntity, ByVal worklog As Entity.WorklogEntity) As Boolean Dim IDALObject As IDAL.IUser Dim IWorklog As IDAL.IWorklog Dim factory As New Factory.LoginFactory IDALObject = factory.CreateUser IWorklog = factory.SaveWorkLog Dim table As DataTable '定义数据库表table作为中间变量 Dim table1 As Boolean '定义中间变量,用于承载User table = IDALObject.IDALUser(User) table1 = IWorklog.SaveWorklog(worklog) '判断是否有记录,如果有返回True,否则false If table.Rows.Count = 0 Then Return False Else Entity.UserEntity.userLevel = table.Rows(0)(6) If IWorklog.SaveWorklog(worklog) Then Return True End If Return True End If End Function End Class
- Facade
'********************************************** '文 件 名:Facade '命名空间:Facade '内 容: '功 能: '文件关系: '作 者:杨倩 '小 组: '生成日期:2016/3/10 20:16:40 '版 本号:V1.0.0.0 '修改日志: '版权说明: '********************************************** Public Class Facade Public Function FactoryUser(ByVal User As Entity.UserEntity, worklog As Entity.WorklogEntity) As String Dim BLLObject As New BLL.UserBLL '实例化b层对象 If BLLObject.BLLUser(User, worklog) = False Then '将user通过facade层传给b层 Return "输入有误" Else Return "登录成功" End If End Function End Class
- UI层
Imports Facade Public Class FrmLogin Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click Dim User As Entity.UserEntity = New Entity.UserEntity '定义一个实体层的对象,用于在各层之间进行传递 Dim strResult As String '定义中间变量User,用于承载实体User Dim FacadeObject As New Facade.Facade '定义一个外观层的对象,用于将U层内容传递到Facade层中 '将文本框内容传递给User实体对象 User.UserID = txtUsername.Text.Trim() User.Password = txtPassword.Text.Trim() Dim worklog As New Entity.WorklogEntity worklog.UserID = User.UserID worklog.loginDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") worklog.Computer = System.Net.Dns.GetHostName().ToString() worklog.Level = Entity.UserEntity.userLevel '判断用户名和密码是否为空" If txtUsername.Text.Trim = "" Then MessageBox.Show("请输入用户名!", "温馨提示") txtUsername.Text = "" txtPassword.Text = "" txtUsername.Focus() Exit Sub End If If txtPassword.Text.Trim = "" Then MessageBox.Show("请输入用户名!", "温馨提示") txtUsername.Text = "" txtPassword.Text = "" txtPassword.Focus() Exit Sub End If 'Try '将User通过U层传给外观 strResult = FacadeObject.FactoryUser(User, worklog) Select Case strResult Case "输入有误" MsgBox("输入有误,请重新输入") txtUsername.Text = "" txtPassword.Text = "" txtUsername.Focus() Case "登录成功" MessageBox.Show("登录成功!", "恭喜你") Entity.WorklogEntity.login_DateTime = worklog.loginDateTime Me.Hide() FrmMain.Show() End Select End Sub End Class