一、概述
初识三层,就是将整个业务应用划分为:用户界面层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。区分层次的目的即为了“高内聚,低耦合”的思想。那各层如何各司其职?
1、UI:通俗讲就是展现给用户的界面,即用户在使用一个系统的时候他的所见所得。
2、BLL:针对具体问题的操作,对业务逻辑的处理。例如登录业务的判断用户名和密码正确与否。
3、DAL:对数据库的操作,包括对数据的增删改查。
那么三层之间是如何引用、传递数据的?这里必须得有实体(Entity)的影子。因为所有的数据都是通过实体传递的,所以各层都引用实体,但是实体不引用任何一层。需要注意,实体并不是三层中的一层,它更是一个类库,用来封装数据。所以这也就是我们说的传实体和传参的区别了。
学习设计模式的时候也说过反射+配置文件实现数据访问程序,其实很不懂。敲了简单的VB.NET登录实例,再次加抽象工厂+反射+配置文件,才又重回头看设计模式的内容,感觉时间就是一剂良药,当初那么的不懂,随着时间的洗涤,也慢慢的清晰!那么加了抽象工厂,各层的结构是怎样的呢?
(这个包图里有个小错误,DAL层的类要去实现接口类)
二、实践
1、设计方案:
2、各层代码:
UI层:
Imports Entity
Imports BLL
Public Class Login
Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
Dim entityUser As New Entity.UserEntity
Dim bllUser As New BLL.UserBLL
entityUser.UserName = txtUserName.Text.Trim
entityUser.PassWord = txtPassword.Text
If txtUserName.Text = "" Then
MessageBox.Show("请输入用户名!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Information)
Exit Sub
ElseIf txtPassword.Text = "" Then
MessageBox.Show("请输入密码!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Information)
Exit Sub
End If
If bllUser.GetBase(entityUser) Then
MsgBox("登录成功!", vbOKOnly + vbInformation, "提示")
Exit Sub
Else
MsgBox("登录失败!", vbOKOnly + vbInformation, "提示")
Exit Sub
End If
End Sub
End Class
BLL层:
Imports Entity
Imports [Interface]
Imports Factory
Public Class UserBLL
Public Function GetBase(ByVal entityUser As Entity.UserEntity) As Boolean
Dim DalF As New Factory.Factory
Dim entityUserB As New Entity.UserEntity
entityUserB = DalF.Interface_User.GetBase(entityUser)
If entityUserB.PassWord = entityUser.PassWord Then
Return True
Else
Return False
End If
End Function
End Class
工厂Factory:
Imports [Interface]
Imports System.Reflection
Public Class Factory
Dim DataBase As String = System.Configuration.ConfigurationSettings.AppSettings("DB") 'AppSetting读取配置文件中的类别字符串
Function Interface_User() As [Interface].UserInterface
Dim ClassName As String = DataBase + ".UserDAL"
Return CType(Assembly.Load(DataBase).CreateInstance(ClassName), [Interface].UserInterface)
End Function
End Class
接口Interface
Imports Entity
Public Interface UserInterface
Function GetBase(ByVal entityUserB As Entity.UserEntity) As Entity.UserEntity
End Interface
DAL层:
Imports Entity
Imports [Interface]
Imports System.Data.SqlClient
Public Class UserDAL : Implements [Interface].UserInterface
Dim ConnStr As String = System.Configuration.ConfigurationSettings.AppSettings("ConnStr") '读配置文件
Dim sqlconn As SqlConnection = New SqlConnection(ConnStr) '连接数据库
Public Function GetBase(entityUserB As UserEntity) As Entity.UserEntity Implements UserInterface.GetBase
Dim sqldata As String = "select * from Users where UserName = '" & entityUserB.UserName & " ' "
Dim sqlcmd As New SqlCommand(sqldata, sqlconn)
Dim sqlread As SqlDataReader
Try
sqlconn.Open()
sqlread = sqlcmd.ExecuteReader()
sqlread.Read()
entityUserB.UserName = sqlread.Item("UserName")
entityUserB.PassWord = sqlread.Item("PassWord")
Return entityUserB
Catch ex As Exception
entityUserB.PassWord = ""
Return entityUserB
End Try
End Function
End Class
配置文件:
得放在UI层(在VS项目管理器中,在项目UI右击——添加——新建项,如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings >
<add key ="ConnStr" value ="Data Source=(local);DataBase=Login;user id=sa;password=123456"/>
<add key ="DB" value ="DAL"/>
</appSettings>
</configuration>
添加两个Key,一个是用来连接数据库的字符串,一个是通过反射来产生不同数据库的DAL层,这样一来就可以实现设计模式中的“开闭原则”,如果更换数据库只需要增加类(DAL),而不需要更改,更不需要重新编译。
以上是对三层的初步理解,希望大神们指正!