通常在程序编程中我们所说的三层架构是指:显示层(UI)、逻辑层(BLL)和数据访问层(DAL)。对于这三层来说,分工明确,各自有各自负责的领域。
UI层:1、负责向用户显示数据 2.负责采集用户输入的信息
BLL层:1.从DAL获取数据,以供UI显示 2.从UI中获取指令或数据,经业务逻辑送达到DAL
DAL层:1.主要用于对数据源的增删改查的操作。
通过它们各自负责的领域我们可以看出,BLL层属于中间层,它负责UI和DAL层之间的通信。那么通常我们还会加入一个实体层(Enity):主要负责返回实体,在上述三层之间传递参数。
那么为什么要划分三层呢?
通过划分三层,可以使得各部分功能很好的被封装在一个包中,各自负责各自的功能,互不打扰。这符合面向对象封装的思想。使得各个模块之间达到高内聚、低耦合。以至于一个部分的更换或修改不至于影响到整个项目的实施进程。
那么这三层之间是如何进行通信的呢?
UI层引用BLL层,BLL层引用DAL层,它们三者同时都引用Enity。
可是,为什么不能循环引用(BLL引用UI,DAL引用BLL,DAL引用UI)呢?其实这就是回到了为什么要分三层,分三层是为了封装,如果继续循环引用,那么就跟分三层没有任何区别,各个参数和数据随便传递,没有界限。
在这里,我们要知道Enity是用来供三层之间相互通信,传递数据的。但是基于三层封装的思想,三层在传递参数时,传递的应该是一个实体,而不是实体中的某个参数。这个符合设计模式中的依赖倒转原则,依赖抽象而不依赖细节,其实也就是封装。
为了更清楚理解上述的这些知识。我用VB.NET做了一个三层关于登录的一个小例子:
Enity层:将程序中所要传递的参数进行声明
Public Class LoginEnity ''' <summary> ''' 用户ID ''' </summary> ''' <remarks></remarks> Private User_ID As Integer Public Property UserID() As String Set(value As String) User_ID = value End Set Get Return User_ID End Get End Property ''' <summary> ''' 用户名 ''' </summary> ''' <remarks></remarks> Private User_Name As String Public Property UserName() As String Set(value As String) User_Name = value End Set Get Return User_Name End Get End Property ''' <summary> ''' 用户密码 ''' </summary> ''' <remarks></remarks> Private _pwd As String Public Property Password() Set(value) _pwd = value End Set Get Return _pwd End Get End Property End Class
UI层:引用BLL的业务逻辑进行显示数据
Private Sub ButLogin_Click(sender As Object, e As EventArgs) Handles ButLogin.Click Dim user As New Enity.LoginEnity '实例化实体 user.UserName = txtUserName.Text user.Password = txtPassword.Text Dim managerBLL = New BLL.LoginBLL 'UI层引用BLL层 If managerBLL.UserIsExist(user) = True Then '利用BLL层中的函数进行逻辑判断 frmQuery.Show() Else MessageBox.Show("登录失败!") End If End Sub
BLL层:引用DAL进行逻辑判断
Public Function UserIsExist(ByVal user As Enity.LoginEnity) As Boolean '注意这里传递的为一个实体,而不是具体的某个参数 Dim manager As New DAL.LoginDAL '引用DAL层,进行实例化 Dim Euser As New Enity.LoginEnity '引用实体层 Try Euser = manager.UserIsExist(user) '利用DAL中的函数进行验证 If user.UserName = Euser.UserName And user.Password = Euser.Password Then'进行逻辑判断 Return True Else Return False End If Catch ex As Exception '对DAL层中抛出的错误进行错误处理 Return False End Try End Function
DAL层:主要负责对数据源中数据的增删改查等操作。
Public Function UserIsExist(ByVal user As Enity.LoginEnity) As Enity.LoginEnity ’参数传递为实体 '进行数据库连接相关代码的编写 Dim sqlConn = New SqlConnection(DbUtil.strConn) Dim cmdText As String = "select UserName,Password from User_Login where UserName=@UserName and Password=@Password" Dim cmd As New SqlCommand(cmdText, sqlConn) '添加参数 cmd.Parameters.Add(New SqlParameter("@UserName", user.UserName)) cmd.Parameters.Add(New SqlParameter("@Password", user.Password)) Dim reader As SqlDataReader sqlConn.Open() '打开数据连接 reader = cmd.ExecuteReader() '从数据库中读取数据 If (Not user Is Nothing) Then If reader.Read() Then user.UserName = reader.Item("UserName")'与数据源中的数据进行验证,是否一致 user.Password = reader.Item("Password") Else Throw New System.Exception("无记录!") '若不存在此条记录,抛出错误 End If End If Return user sqlConn.Close() '关闭连接 cmd = Nothing End Function
通过以上的小例子,我们可以看出,其实每一个小例子都可以由UI、BLL和DAL这三层构成。而实体层则负责数据传递,它将各个层连接成了一条线。从这种角度讲,每一个程序都是有若干条类似的线组成的。
小结:所谓三层架构,基于面向对象的思想,其实可以看做一种很常用的设计模式。不过这个设计模式是作用于整个程序的一个框架设计,它的应用更加普遍,更加宏观。而我们通常学习的设计模式则是针对于于代码中具体某个业务或是某个领域,它针对的是更加细节的地方。而三层框架的设计和设计模式的共同应用才构成了我们灵活多变的程序设计。