之前在学习第一次机房的时候,就是2层,用户界面,应用逻辑和数据库层,而现在我们用3层来重构机房,这就大大方便了维护,降低了耦合,加强了内聚。下面,我来总结一下3层的有关知识。
【对比】
两层结构的应用软件模型:
三层结构应用软件模型:
逻辑上:UI——BLL——DAL/DB
物理上的三层:
显示层——业务层——数据层
【各个层的作用】
UI层(显示层):
1、向用户展现特定业务数据
2、采集用户的输入信息和操作
原则:用户至上、兼顾简洁
BLL层(逻辑判断层):
1、从DAL中获取数据,以供UI层显示用
2、从UI中获取用户指令和数据,执行业务逻辑
3、从UI中获取用户指令和数据,通过DAL写入数据源
DAL层(数据访问层):
1、从数据源加载数据
2、向数据源写入数据
3、从数据源删除数据
流程:UI→BLL→DAL→BLL→UI
【应用原则】
1、DAL只提供基本的数据访问,不包含任何业务相关的逻辑处理
2、UI只负责显示和采集用户操作,不包含任何的业务相关的逻辑处理
3、BLL负责处理业务逻辑,通过获取UI传来的指令,决定执行业务逻辑,在需要访问数据源的时候直接交给DAL处理,处理完成之后,返回必要的数据给UI
4、UI、BLL、DAL 分别在不同的程序集中,各个层需要通过引用来调用联系:UI→BLL→DAL,其中DAL不引用BLL和UI,BLL需要引用DAL,UI直接引用BLL,可能会间接引用DAL。
【实践出真知】
在做机房的过程中,我先做了几个3层的窗体,下面以登陆为例子来展示一下我的代码:
1、先来看看我的解决方案管理器:
其中,还有一个Model层没有圈出来,因为她是一个比较特殊的“层”:
模型层包含所有与数据库中的表相对应的实体类,显示层、业务逻辑层和数据访问层这三层通过传递实体对象来达到数据传递的目的。简而言之,就是哪个功能需要哪些数据,并把这些数据放在不同的model层的类里面,比如,我的登陆需要UserID和Password,那么我在model层里面创建一个UserInfo这个类,来放我登陆需要的数据。具体代码在后面讲解。
创建完3层之后,就需要添加引用:
比如,在UI层,我就需要引用BLL层和model:
同理:BLL层引用DAL和model,DAL层引用model
这三个层都需要引用model,因为他们都要用到model里面的实体类中的数据(UserID、Password)
2、代码展示
UI层:
<span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class Form1
Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
frmRegister.Show()
Dim manager As New LoginBLL.LoginManager '实例化BLL层
Dim user As New LoginModel.UserInfo '实例化model的实体
user.UserName = txtUserName.Text.Trim '引用model并给他的实体层赋值,将UI中用户输入的数据传递给model
user.Password = txtPassword.Text
manager.UserLogin(user) '调BLL层,括号里面是实例化的UserINfo的实体,让BLL层来判断从UI传入的数据。
MsgBox("登陆用户" + user.UserName)
End Sub
End Class</span>
BLL层:
<span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class LoginManager
Public Function UserLogin(ByVal user As LoginModel.UserInfo) As LoginModel.UserInfo
Dim uDao As New LoginDAL.UserDAO '实例化D层中的UserDAO对象
Dim Uuser As New LoginModel.UserInfo '实例化model层
Uuser = uDao.SelectUser(user) '调用D层,把反馈回出的数据传给实体
If IsNothing(Uuser.UserName) Then '判断从D层返回的数据里是否有用户传入到实体中的数据,UI传入和DAL输出是否一致
Throw New Exception("登陆失败")
Else
'MsgBox("登陆成功")
End If
Return Uuser '将实体user返回到U层
End Function
End Class</span>
Model层:
<span style="font-family:KaiTi_GB2312;font-size:18px;">Public Class UserInfo
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 Class</span>
DAL层:
<span style="font-family:KaiTi_GB2312;font-size:18px;">Imports System.Data.SqlClient
Public Class UserDAO
Public conn As New SqlConnection("Server=TXB;Database=Login;User ID=sa;Password=1") '连接数据库
Public Function SelectUser(ByVal user As LoginModel.UserInfo) As LoginModel.UserInfo '传实体UserInfo以便参数调用
Dim sql As String = "SELECT ID,UserName,Password FROM Users WHERE UserName=@UserName AND Password=@Password" 'SQL查询语句
Dim cmd As New SqlCommand(sql, conn) '构造方法,执行和连接
'添加两个参数@UserName,@Password
cmd.Parameters.Add(New SqlParameter("@UserName", user.UserName))
cmd.Parameters.Add(New SqlParameter("@password", user.Password))
conn.Open() '打开数据连接
Dim reader As SqlDataReader = cmd.ExecuteReader '定义类型为sqlDatareader的变量Rearder,并执行sql语句
Dim Buser As New LoginModel.UserInfo '实例化新的UserInfo
'使用sqldatareader对象read()方法进行逐行读取
While (reader.Read())
Buser.UserName = reader.GetString(1) '获取第一列中的数据
Buser.Password = reader.GetString(2) '获取第二列中的数据
End While
Return Buser '返回对象
conn.Close() '关闭数据连接
End Function
End Class
</span>
3层就介绍到这里,他给我们带来的是易维护,易扩展,低耦合,高内聚,让我们的程序变得干净整洁。