首页 > 代码库 > 三层总结

三层总结

三层总结

         最近开始了三层的学习,还记得去年的这个时候看到师哥们的博客,写的就是三层的东西,感觉好难,但是到了今年的现在,自己看来,感觉还是好多了,下面就把我这几天学习到的三层的东西总结一下,与大家来个交流吧。

三层全称叫做三层架构:通常意义上的三层架构就是将整个业务应用划分为:表现层(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. 三个模块,可以分别运行于不同的服务器吗?

如果不是所有答案都为YES,那么你的项目还不能算是严格意义上的三层程序. 三层程序有一些需要约定遵守的规则:

1. 最关键的,UI层只能作为一个外壳,不能包含任何业务逻辑(BizLogic)的处理过程

2. 设计时应该从BLL出发,而不是UI出发. BLL层在API上应该实现所有BizLogic,以面向对象的方式

3. 不管数据层是一个简单的SqlHelper也好,还是带有Mapping过的Classes也好,应该在一定的抽象程度上做到系统无关

4.不管使用COM+(Enterprise Service),还是Remoting,还是WebService之类的远程对象技术,不管部署的时候是不是真的分别部署到不同的服务器上,最起码在设计的时候要做这样的考虑,更远的,还得考虑多台服务器通过负载均衡作集群

所以考虑一个项目是不是应该应用三层/多层设计时,先得考虑下是不是真的需要? 实际上大部分程序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
            euser2.PWD = txtPassword.Text.Trim                               '将密码传递给实体层的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("登录失败,请检查用户名和密码!")
        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))
        '就是给需要查询的关键字改成参数形式。
        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