一、概述
初识三层,就是将整个业务应用划分为:用户界面层(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),而不需要更改,更不需要重新编译。
以上是对三层的初步理解,希望大神们指正!