您的位置:首页 > 运维架构 > 网站架构

三层架构实战篇——抽象工厂+反射实现验证用户登录!

2012-01-20 16:20 483 查看
一、“三层”架构就一定要分三层吗?

答案当然是否定的,分层的根本目的就是要达到“高内聚,低耦合”。我们不应该为了分层而分层,那么什么样的分层才是最好的分层呢?我认为,没有最好的分层,只有合理的分层。同时,我们也要根据具体的情况来分析,如果系统很small,不用分层也不是不可。当然,对于一些逻辑复杂的大型系统,分层便显得尤重要了,可以达到所说的,利用团队开发、可复用性、表达的业务逻辑清楚、利于维护等等。

二、下面这个Demo展示实现登录系统的功能,其中利用了抽象工厂+反射+配置文件。

下面是架构图,就是三层架构的扩展,在BLL层与DAL层添加了一个工厂层、接口层。






因为在底层运用了抽象工厂,所以可以方便实现不同数据库的访问。假如,现在要用到的数据库变为Access.就可以把DLL层的SQLServerDAL变成AccessDAL即可。

接下来的类图表现的是其中几个类的关系:





在D层,我添加了一个SQLHelp的类,用来处理SQL语句,与建立连接。代码如下:

Public MustInherit Class SQLHelper
Public Shared sConneciton As String = ConfigurationManager.ConnectionStrings("strConnection").ConnectionString
''' <summary>
''' 执行查询操作
''' </summary>
''' <param name="connectionString">连接字符串</param>
''' <param name="cmdType">commandtype store procedure</param>
''' <param name="cmdText">the store procedure name or T-SQL command</param>
''' <param name="para">an array of sqlparamters used to execute the command</param>
''' <returns>datareader</returns>
''' <remarks></remarks>
Public Shared Function ExecuteDataSet(ByVal connectionString As String, ByVal cmdType As String, ByVal cmdText As String, ByVal para() As SqlParameter) As DataSet
Dim dbCon As SqlConnection
Dim dbCmd As SqlCommand
dbCon = New SqlConnection(sConneciton)
dbCmd = New SqlCommand

dbCmd.Connection = dbCon
dbCmd.CommandType = cmdType
dbCmd.CommandText = cmdText
dbCmd.Parameters.AddRange(para)

Dim dt As New DataSet

dbCon.Open()    '打开数据库连接

Dim dr As SqlDataReader
dr = dbCmd.ExecuteReader
dt.Load(dr, Data.LoadOption.Upsert, "user")
Return dt

'Dim dataAdapater As SqlDataAdapter
'dataAdapater = New SqlDataAdapter(dbCmd)
'dataAdapater.Fill(dt)
'Return dt
End Function


下面是DataAccess工厂类,通过接口,确定实例化哪个类。其中用到了反射,为了方便日后数据库维护(只需要将SQLServerDAL类换成AccessDAL类,并用相应的语法实现接口即可。代码如下:

Public Class DataAccess
Private Shared db As String = ConfigurationManager.AppSettings("db")       '也要生成为静态的,否则出错
''' <summary>
''' 获得接口实例
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Function CreatUsers() As IUsers
Dim className As String
className = db + ".Users"
Dim result As IUsers
result = CType(Assembly.Load(db).CreateInstance(className), IUsers)
Return result
End Function
End Class


下面是IUser接口类:

Public Interface IUsers

''' <summary>
''' 根据userID读取usersinfo
''' </summary>
''' <param name="strUserID">用户名</param>
''' <returns>userinfo</returns>
''' <remarks></remarks>
Function GetUser(ByVal strUserID As String) As UsersInfo

End Interface


下面是SQLServerDAL下的Users类(逻辑实体)

Public Class Users : Implements IUsers
''' <summary>
''' 取得给定用户名的实体
''' </summary>
''' <param name="strUserID"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetUser(ByVal strUserID As String) As Model.UsersInfo Implements IDAL.IUsers.GetUser
Dim sql As String
sql = "select * from Login where userID=@ID"
Dim dt As New DataSet
Dim para() As SqlParameter = {New SqlParameter("@ID", strUserID)}

dt = SQLHelper.ExecuteDataSet(SQLHelper.sConneciton, CommandType.Text, sql, para)

Dim user As UsersInfo
user = New UsersInfo(Convert.ToString(dt.Tables(0).Rows(0).Item("userID")), Convert.ToString(dt.Tables(0).Rows(0).Item("Userpassword")))
Return user
End Function
End Class


下面是BLL层的验证类:


Public Class Verify
''' <summary>
''' 查询数据库,验证用户是否存在
''' </summary>
''' <param name="strUserID">传入用户名ID</param>
''' <returns>返回查询结果,true or false</returns>
''' <remarks></remarks>
Public Shared Function VerifyUser(ByVal strUserID As String, ByVal strPassWord As String) As Boolean
Dim user As UsersInfo
Dim IUser As IUsers
' Dim dbAccess As New DataAccess      '工厂用静态的方法,工厂实例化没有意义

IUser = DataAccess.CreatUsers
'根据给定的UserID查数据库
user = IUser.GetUser(strUserID)
'如果根据给定的用户名查到的记录的passwod也相等的话,那么,验证成功,返回true,否则返回false
If user.PassWord = strPassWord Then
Return True
Else
Return False
End If
End Function
End Class


觉得不妥的地方就是没有例外处理……

欢迎大家交流讨论!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: