三层总结
近期開始了三层的学习。还记得去年的这个时候看到师哥们的博客。写的就是三层的东西,感觉好难。可是到了今年的如今。自己看来,感觉还是好多了,以下就把我这几天学习到的三层的东西总结一下,与大家来个交流吧。
三层全称叫做三层架构:通常意义上的三层架构就是将整个业务应用划分为:表现层(UI)、业务逻辑层(BLL)、数据訪问层(DAL)。
区分层次的目的即为了“高内聚,低耦合”的思想。
说到三层,首先为大家举个样例,饭馆我们都去过,路边的小吃摊我们也去过。有没有发现什么不同呢?
当我们去小吃摊时。常常是你要的东西不是忘了给你做一部分,活着就是上一个你没有要的,这是为什么呢,由于我们把全部的业务都交给了小哥一个人处理,可惜,他不是全能战士,所以就导致了我们的吃饭的不痛快。
但是在饭馆呢?当我们要东西时,我们找的是服务员,而他也仅仅是单单的为我们展现食料,怎样做出来是由厨师完毕,而须要什么食材,则是由购员去购买,这样就构成了一个饭馆的高内聚。低耦合,将业务层分开从而使工作的效率更高。
如今大家大概能够理解为什么要分层了吧。
那么回过头来咱们说说计算机中的三层
分类
1.表现层(UI)展现给用户的界面,即用户在使用一个系统的时候所见所得。
作用:向用户展示特定业务数据
採集用户的数据信息和操作
设计原则:
用户至上,兼顾简洁
2.业务逻辑层(BLL)针对详细问题的操作。也能够所看到的对数据层的操作。对数据业务逻辑处理。
作用:
从DAL中获取数据,已提供UI显示用
从UI中获取用户指令和数据,运行业务逻辑
从UI中获取用户指令和数据。通过DAL写入数据源
职责机制
UI--->BLL--->UI
UI--->BLL--->DAL--->BLL--->UI
3.数据訪问层(DAL):直接操作数据库针对数九的增删改查。
DAL的作用:
从数据源载入数据(Select)
向数据源写入数据(Insert/Update)
从数据源删除数据(Delete)
4.实体层
实体层会贯穿于三层中,參与数据的推断,所以有人把他会单独的分开,而我更倾向于把它判定到业务逻辑层。
三层结构的程序不是说把项目分成DAL,BLL,WebUI三个模块就叫三层了。以下几个问题在你的项目里面:
1. UILayer里面仅仅有少量(或者没有)SQL语句或者存储过程调用。而且这些语句保证不会改动数据?
2. 假设把UILayer拿掉。你的项目还能在Interface/API的层次上提供全部功能吗?
3.你的DAL能够移植到其它类似环境的项目吗?
4. 三个模块,能够分别执行于不同的server吗?
假设不是全部答案都为YES,那么你的项目还不能算是严格意义上的三层程序. 三层程序有一些须要约定遵守的规则:
1. 最关键的,UI层仅仅能作为一个外壳。不能包括不论什么业务逻辑(BizLogic)的处理过程
2. 设计时应该从BLL出发,而不是UI出发. BLL层在API上应该实现全部BizLogic,以面向对象的方式
3. 无论数据层是一个简单的SqlHelper也好,还是带有Mapping过的Classes也好,应该在一定的抽象程度上做到系统无关
4.无论使用COM+(Enterprise Service),还是Remoting,还是WebService之类的远程对象技术。无论部署的时候是不是真的分别部署到不同的server上。最起码在设计的时候要做这种考虑,更远的,还得考虑多台server通过负载均衡作集群
所以考虑一个项目是不是应该应用三层/多层设计时,先得考虑下是不是真的须要?
实际上大部分程序WebApplication就足够了。全然不是必需去分层。
下边为大家咱先一段简单的三层代码,仅供參考。
实体层
Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles btnLogin.Click Try '获得表现层的数据,将数据传给BLL层 Dim euser2 As New Entity.Userinfo '实例化新的UserInfo。用来传递B层的实体 Dim euser3 As Entity.Userinfo '定义一个类型为UserInfo的參数,用来赋值 euser2.UserName = txtUserName.Text.Trim '将username传递给实体层的UserName euser2.PWD = txtPassword.Text.Trim '将password传递给实体层的PWD '调用B层。推断登陆 Dim mgr As New UserBLL.LoginManager euser3 = mgr.UserLogin(euser2) Catch ex As Exception MessageBox.Show(ex.Message.ToString()) End Try End Sub End Class
业务逻辑层(BLL)
Public Class LoginManager Public Function UserLogin(ByVal User As Entity.UserInfo) As Entity.UserInfo Dim uDao As New UserDAL.UserDAO '实例化D层中新的UserDAO对象 Dim eUser1 As Entity.UserInfo '定义一个类型为实体层UserInfo的參数,用于赋值 eUser1 = uDao.SelectUser(User) '推断是否查询到记录。若有,登录成功,并返回实体euser1 If IsNothing(eUser1.UserName) Then Throw New Exception("登录失败,请检查username和password!") Else MsgBox("登录成功" + eUser1.UserName) Return eUser1 End If End Function End Class数据訪问层(DAL)
Imports System.Data Imports System.Data.SqlClient Imports Entity 'D层。仅仅涉及到对数据的操作,须要引用实体层Entity Public Class UserDAO '创建数据库连接 Private str As String = "server=192.168.24.172;database=jf_charge;uid=sa;pwd=123456" Public Function SelectUser(ByVal User As UserInfo) As Entity.UserInfo '传实体UserInfo,而不是參数ID、UserName等。这样可方便对实体中的參数进行调用 Dim reader As SqlDataReader '定义类型为sqlDatareader的变量reader Dim eUser As New Entity.UserInfo '实例化新的UserInfo Dim conn As SqlConnection = New SqlConnection(str) '代码中的@UserName和@PWD採用了參数的方式来写字符串。是为了防止SQL的注入。而cmd.Parameters.Add(New SqlParameter("@UserName", User.UserName)) '就是给须要查询的keyword改成參数形式。 Dim sql As String = "Select UserName,PWD From User_info Where UserName=@UserName And PWD=@PWD" Dim cmd As New SqlCommand(sql, conn) '创建sqlCommand对象 cmd.Parameters.Add(New SqlParameter("@UserName", User.UserName)) '若用成eUser.UserName则会出现參数未传递的错误提示 cmd.Parameters.Add(New SqlParameter("@PWD", User.PWD)) conn.Open() '打开数据连接 reader = cmd.ExecuteReader() '运行查询语句,并生成一个DataReader '读取查询到的数据。并返回给对应的属性 While reader.Read() '获取数据库中对应字段的数据 '数组必须从零開始读取,否则会超出其界限 eUser.UserName = reader.GetString(0) eUser.PWD = reader.GetString(1) End While Return eUser '返回查询到的实体 conn.Close() '关闭连接 End Function End Class
实体层(Entity)
Public Class Userinfo 'UserName属性 Private _username As String Public Property UserName As String Get Return _username End Get Set(value As String) _username = value End Set End Property 'PWD属性 Private _pwd As String Public Property PWD As String Get Return _pwd End Get Set(value As String) _pwd = value End Set End Property End Class