日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

抽象工厂+反射+依赖注入 实现对数据访问层和业务逻辑层的优化

發(fā)布時間:2025/6/15 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 抽象工厂+反射+依赖注入 实现对数据访问层和业务逻辑层的优化 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

分層思想的一個核心就是部件化,各個層之間是相互獨立的,每一層可以隨便抽取換成一個其他語言的版本,但只要與相應的接口吻合就行。

我用的三層架構大致是這樣的,基本的三層就不說了,然后分別為業(yè)務邏輯層和數(shù)據(jù)訪問層定義一個接口,由具體的那個層來實現(xiàn),問題產生了,由誰來指定程序使用哪個具體的對象來實現(xiàn)相應接口?

為解決這個問題,我應用的是抽象工廠模式。分別為業(yè)務邏輯層和數(shù)據(jù)訪問層添加一個抽象工廠。具體架構還是看下圖吧。

這里的Utility是一個工具類,在下文中會提到。

學過設計模式的人都應該聽過反射技術,但是一個系統(tǒng)中用到的類很多,需要對每一個類進行實例化,如果僅利用抽象工廠+反射模式,重復的代碼比較多,如果哪一天整個DAL層發(fā)生變更,那么就要在代碼中修改每一個用到的地方,不僅不容易維護,而且還很容易出錯,未解決這個問題,對程序作了一個優(yōu)化——用到依賴注入。還是看看代碼吧。

1、先看看依賴注入的容器:這里我把這個注入容器放到了工具類中,剛開始學習設計模式,不知道是否合理,歡迎高手們指點。

[vb]?view plaincopy
  • Imports?System.Configuration??
  • Imports?System.Reflection??
  • Public?Class?DependencyInjector??
  • ??
  • ????'''?<summary>??
  • ????'''?利用反射機制,取得數(shù)據(jù)訪問層對象??
  • ????'''?</summary>??
  • ????'''?<param?name="className">傳入數(shù)據(jù)訪問層中要實例化的類的名稱</param>??
  • ????'''?<returns>指定的數(shù)據(jù)訪問層的類</returns>??
  • ????'''?<remarks></remarks>??
  • ????Public?Function?GetDALObject(ByVal?className?As?String)?As?Object??
  • ????????Dim?dal?As?Object??
  • ????????Dim?dalName?As?String??
  • ????????Dim?fullClassName?As?String??
  • ????????Dim?dalObj?As?Object??
  • ??
  • ????????'通過配置文件的指定要應用的DAL層??
  • ????????dal?=?System.Configuration.ConfigurationManager.AppSettings("DAL")??
  • ??
  • ????????'dalName就是常說的用用程序的名稱??
  • ????????dalName?=?dal.ToString??
  • ??
  • ????????'命名空間+類的名稱,指明要實例化的類的路徑??
  • ????????fullClassName?=?dalName?+?"."?+?className??
  • ????????'通過反射,取得數(shù)據(jù)訪問層對象??
  • ????????dalObj?=?Assembly.Load(dalName).CreateInstance(fullClassName)??
  • ????????'返回指定的對象??
  • ????????Return?dalObj??
  • ??
  • ????End?Function??
  • ??
  • ??
  • ????'''?<summary>??
  • ????'''取得指定業(yè)務邏輯層的指定類??
  • ????'''?</summary>??
  • ????'''?<param?name="className">要應用的業(yè)務邏輯層的具體類的名稱</param>??
  • ????'''?<returns>指定的業(yè)務邏輯層的類(對象)</returns>??
  • ????'''?<remarks></remarks>??
  • ????Public?Function?GetBLLObject(ByVal?className?As?String)?As?Object??
  • ??
  • ????????Dim?bll?As?Object??
  • ????????Dim?bllName?As?String??
  • ????????Dim?bllObj?As?Object??
  • ????????Dim?fullClassName?As?String??
  • ??
  • ????????'從配置文件中讀取業(yè)務邏輯名稱??
  • ????????bll?=?System.Configuration.ConfigurationManager.AppSettings("BLL")??
  • ????????bllName?=?bll.ToString??
  • ??
  • ????????fullClassName?=?bllName?+?"."?+?className??
  • ??
  • ????????'利用反射取得業(yè)務邏輯層對象??
  • ????????bllObj?=?Assembly.Load(bllName).CreateInstance(fullClassName)??
  • ??
  • ????????Return?bllObj??
  • ??
  • ????End?Function??
  • End?Class??
  • 2、相關配置文件:

    [html]?view plaincopy
  • <appSettings>??
  • ????<add?key="connStr"??value="Persist?Security?Info=true;Data?Source=*****;Initial?Catalog=Charge_Sys_SelfDesign;User?ID=sa;PWD=****;"?/>??
  • ????<add?key="DAL"??value="DAL"?/>??
  • ????<add?key="BLL"??value="BLL"?/>??????
  • ??</appSettings>??
  • 3、業(yè)務邏輯層工廠:這里以在工廠中生產一個UserBLL類為例,在工廠中添加CreateUserBLL()方法,理論上講,業(yè)務邏輯層有多少個類在此工廠中就要有多少個相應的方法,但是針對不同語言寫的或者是不同的程序員用同一種語言寫的同一層的代碼(但都實現(xiàn)了程序指定的接口),我們在給類起名字的時候,只要用相同的類名就可以通過僅修改配置文件,達到換層的目的,而無需在工廠中改動任何代碼。比如說,我現(xiàn)在要把DAL層換成AccessDAL,那么僅需要做如下修改即可。

    [html]?view plaincopy
  • <add?key="DAL"??value="AccessDAL"?/>??
  • 這就是分層的好處,當然也是面向對象思想的優(yōu)勢了。

    上面主要是解釋了一下配置文件,來看看業(yè)務邏輯工廠代碼:

    [vb]?view plaincopy
  • Imports?IBLL??
  • Imports?Utility??
  • Imports?System.Configuration??
  • Imports?System.Reflection??
  • Imports?System.Windows.Forms??
  • Public?Class?CreateBLL??
  • ??
  • ????Private?dependecy?As?New?Utility.DependencyInjector??
  • ??
  • ????'''?<summary>??
  • ????'''?生成用戶業(yè)務邏輯層訪問對象??
  • ????'''?</summary>??
  • ????'''?<returns></returns>??
  • ????'''?<remarks></remarks>??
  • ????Public?Function?CreateUserBLL()?As?IBLL.IUserBLL??
  • ????????Try??
  • ????????????'如果不用注入,需要重復N次BLL,??
  • ????????????'Return?CType(Assembly.Load("BLL").CreateInstance("BLL.UserBLL"),?IBLL.IUserBLL)??
  • ????????????'優(yōu)化后只需指明具體類名,如果要換層,只需到配置文件中做簡單修改即可,程序代碼清晰,不宜出錯。??
  • ????????????Return?CType(dependecy.GetBLLObject("UserBLL"),?IBLL.IUserBLL)??
  • ????????Catch?ex?As?Exception??
  • ????????????MsgBox(ex.Message)??
  • ????????????Return?Nothing??
  • ????????End?Try??
  • ????End?Function??
  • End?Class??
  • 4、數(shù)據(jù)訪問層工廠代碼類似:

    [vb]?view plaincopy
  • Imports?Utility??
  • Imports?System.Configuration??
  • Imports?System.Reflection??
  • Imports?IDAL??
  • Imports?System.Windows.Forms??
  • ??
  • Public?Class?CreateDAL??
  • ??
  • ????Private?dependency?As?New?Utility.DependencyInjector??
  • ??
  • ????'''?<summary>??
  • ????'''?生成用戶指定的數(shù)據(jù)訪問層對象??
  • ????'''?</summary>??
  • ????'''?<returns></returns>??
  • ????'''?<remarks></remarks>??
  • ????Public?Function?CreateUserDAL()?As?IDAL.IUserDAL??
  • ????????Try??
  • ????????????'Return?CType(Assembly.Load("DAL").CreateInstance("DAL.UserDAL"),?IDAL.IUserDAL)??
  • ????????????Return?CType(dependency.GetDALObject("UserDAL"),?IDAL.IUserDAL)??
  • ????????Catch?ex?As?Exception??
  • ????????????MessageBox.Show(ex.Message)??
  • ????????????Return?Nothing??
  • ????????End?Try??
  • ??
  • ????End?Function??
  • End?Class??
  • 5、業(yè)務邏輯層接口代碼比較簡單,只需要定義一些相關接口方法即可,但是這里面體現(xiàn)了系統(tǒng)的架構,看似代碼簡單,實則反應程序員的架構水平。

    [vb]?view plaincopy
  • Public?Interface?IUserBLL??
  • ??
  • ????'返回用戶登錄的身份級別,在接口的實現(xiàn)中要驗證用戶名和密碼??
  • ????Function?LogIn(ByVal?modelUser?As?Model.User)?As?String??
  • ??
  • End?Interface??
  • 6、數(shù)據(jù)訪問層接口:

    [vb]?view plaincopy
  • Public?Interface?IUserDAL??
  • ??
  • ????'獲取用戶ID??
  • ????Function?GetID(ByVal?modelUser?As?Model.User)?As?String??
  • ????'獲取用戶密碼??
  • ????Function?GetPwd(ByVal?modelUser?As?Model.User)?As?String??
  • ????'獲取用戶級別??
  • ????Function?GetLevel(ByVal?modelUser?As?Model.User)?As?String??
  • ??
  • End?Interface??
  • 7、業(yè)務邏輯層:

    [vb]?view plaincopy
  • Imports?DALFactory??
  • Imports?IBLL??
  • Imports?IDAL??
  • Imports?Model??
  • Imports?System.Data.SqlClient??
  • Imports?System.Collections.Generic??
  • Public?Class?UserBLL??
  • ????Implements?IBLL.IUserBLL??
  • ????Private?dalFactory?As?New?DALFactory.CreateDAL??
  • ????'''?<summary>??
  • ????'''?先判斷用戶名和密碼是否正確,然后返回用戶級別??
  • ????'''?</summary>??
  • ????'''?<param?name="modelUser">用戶實體類</param>??
  • ????'''?<returns>用戶級別</returns>??
  • ????'''?<remarks></remarks>??
  • ????Public?Function?LogIn(ByVal?modelUser?As?Model.User)?As?String?Implements?IBLL.IUserBLL.LogIn??
  • ????????Dim?userLevel?As?String??
  • ????????Try??
  • ????????????If?dalFactory.CreateUserDAL.GetID(modelUser)?=?""?Then??
  • ????????????????MsgBox("用戶名錯誤!")??
  • ????????????????Return?Nothing??
  • ????????????????Exit?Function??
  • ????????????End?If??
  • ????????????If?dalFactory.CreateUserDAL.GetPwd(modelUser)?=?""?Then??
  • ????????????????MsgBox("密碼名錯誤!")??
  • ????????????????Return?Nothing??
  • ????????????????Exit?Function??
  • ????????????End?If??
  • ??
  • ??
  • ????????????'通過數(shù)據(jù)訪問層工廠指定實現(xiàn)數(shù)據(jù)訪問層接口的具體的數(shù)據(jù)訪問層以及該層的具體類??
  • ????????????userLevel?=?dalFactory.CreateUserDAL.GetLevel(modelUser)??
  • ??
  • ??
  • ????????Catch?ex?As?Exception??
  • ????????????Return?Nothing??
  • ????????End?Try??
  • ????????Return?userLevel??
  • ????End?Function??
  • End?Class??
  • ?

    8、數(shù)據(jù)訪問層:

    [vb]?view plaincopy
  • Imports?System.Data.SqlClient??
  • Imports?Utility??
  • Imports?System.Windows.Forms??
  • ??
  • Public?Class?UserDAL??
  • ????'實現(xiàn)數(shù)據(jù)訪問層的接口??
  • ????Implements?IDAL.IUserDAL??
  • ????Private?sqlHelp?As?New?Utility.SQLServerDALHelp??
  • ????'''?<summary>??
  • ????'''?讀取用戶ID??
  • ????'''?</summary>??
  • ????'''?<param?name="modelUser">用戶實體類</param>??
  • ????'''?<returns>用戶ID</returns>??
  • ????'''?<remarks></remarks>??
  • ????Public?Function?GetID(ByVal?modelUser?As?Model.User)?As?String?Implements?IDAL.IUserDAL.GetID??
  • ????????Dim?User_ID?As?String??
  • ????????Dim?conn?As?New?SqlConnection(sqlHelp.connStr)??
  • ????????Dim?spName?As?String??
  • ????????spName?=?"proc_GetUserID"??
  • ????????Dim?cmd?As?New?SqlCommand(spName,?conn)??
  • ????????cmd.CommandType?=?CommandType.StoredProcedure??
  • ????????Dim?Param?As?SqlParameter??
  • ????????Param?=?New?SqlParameter("@User_ID",?SqlDbType.VarChar)??
  • ????????Param.Value?=?modelUser.User_ID??
  • ????????cmd.Parameters.Add(Param)??
  • ??
  • ????????Try??
  • ????????????conn.Open()??
  • ????????????User_ID?=?cmd.ExecuteScalar.ToString??
  • ????????????Return?User_ID??
  • ????????Catch?ex?As?Exception??
  • ????????????MsgBox(ex.Message)??
  • ????????????Throw?New?Exception(ex.Message)??
  • ????????Finally??
  • ????????????conn.Close()??
  • ????????????cmd.Dispose()??
  • ????????????cmd?=?Nothing??
  • ????????End?Try??
  • ????????Return?User_ID??
  • ????End?Function??
  • ????'''?<summary>??
  • ????'''?讀取用戶密碼??
  • ????'''?</summary>??
  • ????'''?<param?name="modelUser">用戶實體類</param>??
  • ????'''?<returns>密碼</returns>??
  • ????'''?<remarks></remarks>??
  • ????Public?Function?GetPwd(ByVal?modelUser?As?Model.User)?As?String?Implements?IDAL.IUserDAL.GetPwd??
  • ????????Dim?user_Pwd?As?String??
  • ????????Dim?spName?As?String??
  • ????????spName?=?"proc_GetUserPwd"??
  • ????????Dim?conn?As?New?SqlConnection(sqlHelp.connStr)??
  • ????????Dim?cmd?As?New?SqlCommand(spName,?conn)??
  • ????????cmd.CommandType?=?CommandType.StoredProcedure??
  • ??
  • ????????Dim?Param?As?SqlParameter??
  • ????????Param?=?New?SqlParameter("@User_Pwd",?SqlDbType.VarChar)??
  • ????????Param.Value?=?modelUser.User_Pwd??
  • ????????cmd.Parameters.Add(Param)??
  • ??
  • ????????Param?=?New?SqlParameter("@User_ID",?SqlDbType.VarChar)??
  • ????????Param.Value?=?modelUser.User_Pwd??
  • ????????cmd.Parameters.Add(Param)??
  • ????????Try??
  • ????????????conn.Open()??
  • ????????????user_Pwd?=?cmd.ExecuteScalar.ToString??
  • ????????Catch?ex?As?Exception??
  • ????????????MsgBox(ex.Message)??
  • ????????????Throw?New?Exception(ex.Message)??
  • ????????Finally??
  • ????????????conn.Close()??
  • ????????????cmd.Dispose()??
  • ????????????cmd?=?Nothing??
  • ????????End?Try??
  • ????????Return?user_Pwd??
  • ????End?Function??
  • ????'''?<summary>??
  • ????'''?讀取用戶身份級別??
  • ????'''?</summary>??
  • ????'''?<param?name="modelUser">用戶實體類</param>??
  • ????'''?<returns>身份級別</returns>??
  • ????'''?<remarks></remarks>??
  • ????Public?Function?GetLevel(ByVal?modelUser?As?Model.User)?As?String?Implements?IDAL.IUserDAL.GetLevel??
  • ????????Dim?User_Level?As?String??
  • ????????Dim?spName?As?String??
  • ????????spName?=?"proc_GetUserLevel"??
  • ????????Dim?conn?As?New?SqlConnection(sqlHelp.connStr)??
  • ????????Dim?cmd?As?New?SqlCommand(spName,?conn)??
  • ????????cmd.CommandType?=?CommandType.StoredProcedure??
  • ??
  • ????????Dim?Param?As?SqlParameter??
  • ????????Param?=?New?SqlParameter("@User_ID",?SqlDbType.VarChar)??
  • ????????Param.Value?=?modelUser.User_ID??
  • ????????cmd.Parameters.Add(Param)??
  • ????????Try??
  • ????????????conn.Open()??
  • ????????????User_Level?=?cmd.ExecuteScalar.ToString??
  • ????????Catch?ex?As?Exception??
  • ????????????MsgBox(ex.Message)??
  • ????????????Throw?New?Exception(ex.Message)??
  • ????????Finally??
  • ????????????conn.Close()??
  • ????????????cmd.Dispose()??
  • ????????????cmd?=?Nothing??
  • ????????End?Try??
  • ????????Return?User_Level??
  • ????End?Function??
  • End?Class??
  • 9、總算到UI層了:注意這里還沒有添加針對用戶輸入合法性的驗證,如,用戶名、密碼輸入是否為空,是否符合指定格式等。

    [vb]?view plaincopy
  • Imports?Model??
  • Imports?IBLL??
  • Imports?System.Collections.Generic??
  • Imports?BLLFactory??
  • Public?Class?frmLogIn??
  • ??
  • ????Private?bllFactory?As?New?BLLFactory.CreateBLL??
  • ????Private?Sub?btnLogIn_Click(ByVal?sender?As?System.Object,?ByVal?e?As?System.EventArgs)?Handles?btnLogIn.Click??
  • ????????Dim?modelUser?As?New?Model.User??
  • ????????Dim?userLevel?As?String??
  • ??
  • ????????modelUser.User_ID?=?txtUserID.Text??
  • ????????modelUser.User_Pwd?=?txtUserPwd.Text??
  • ??
  • ??
  • ????????'通過業(yè)務邏輯工廠指定業(yè)務邏輯接口要使用的具體的業(yè)務邏輯層中的具體類??
  • ????????userLevel?=?bllFactory.CreateUserBLL.LogIn(modelUser)??
  • ??
  • ??
  • ????????Select?Case?userLevel??
  • ????????????Case?"一般用戶"??
  • ??
  • ????????????Case?"操作員"??
  • ??
  • ????????????Case?"管理員"??
  • ????????????????frmMDIParentForm.Show()??
  • ??????????????
  • ????????????Case?Else??
  • ????????????????MsgBox("未知錯誤!")??
  • ????????????????Exit?Sub??
  • ????????End?Select??
  • ????End?Sub??
  • ??
  • ????Private?Sub?btnExit_Click(ByVal?sender?As?System.Object,?ByVal?e?As?System.EventArgs)?Handles?btnExit.Click??
  • ????????txtUserID.Text?=?""??
  • ????????txtUserPwd.Text?=?""??
  • ????????Me.Close()??
  • ????End?Sub??
  • ?????
  • End?Class??
  • 到此為止,一個簡單的三層架構就算實現(xiàn)了,隱約感覺設計上有些地方不合理,但說不好存在于哪些地方,希望由此路過的大牛們,多多指教,另外,這里的數(shù)據(jù)訪問層代碼冗余較多,在后續(xù)的博客中,會通過編寫一個SQLHelp來實現(xiàn)優(yōu)化,還有UML包圖也會在后續(xù)博客中天上。

    最后說說我自己的感觸。

    針對架構:用到了兩個抽象工廠,剛開始是將兩個工廠寫到了一層中,這層的名稱就叫Factory,而且封裝注入的類也一并放到了這層中,但是在調試程序的時候出現(xiàn)DAL層依賴循環(huán)調用錯誤,不知道是代碼還是設計上的原因?

    針對接口設計:不太清楚業(yè)務邏輯層的方法設計是否合理,現(xiàn)在的一個問題就是如果用戶名或者密碼出錯的話,并不是由UI層向用戶提供反饋信息,而是由業(yè)務邏輯層擔當了此任務,暫且就這么寫吧,估計到后面寫的多了就找到合適的方法了。

    總結

    以上是生活随笔為你收集整理的抽象工厂+反射+依赖注入 实现对数据访问层和业务逻辑层的优化的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。