在做系統的時候有意識的用到了抽象工廠這個設計模式,主要解決的是數據庫更換的問題。
下面就以簡單的登錄來逐步的分析一下這個模式。
經典的三層架構
數據庫如下
1. 一般的數據庫連接方式
界面層
1:
Public
Class
Login
2:
Private
Sub
btnLogin_Click(
ByVal
sender
As
System.
Object
,
ByVal
e
As
System.EventArgs)
Handles
btnLogin.Click
3:
Dim
LUser
As
New
Entity.User
4:
Dim
BCheck
As
New
BLL.B_Login
5:
LUser.User_ID = txtName.Text
6:
LUser.User_Pwd = txtPwd.Text
7:
If
BCheck.Check(LUser) =
True
Then
8:
MsgBox(
"登錄成功!"
)
9:
Else
10:
MsgBox(“
"登錄失??!"
)
11:
End
If
12:
End
Sub
13:
14:
Private
Sub
btnCancle_Click(
ByVal
sender
As
System.
Object
,
ByVal
e
As
System.EventArgs)
Handles
btnCancle.Click
15:
End
16:
End
Sub
17:
End
Class
業務邏輯層
1:
Public
Class
B_Login
2:
Function
Check(
ByVal
User
As
Entity.User)
As
Boolean
3:
Dim
DaUser
As
New
DAL.D_UserInfo
4:
Dim
BlUser
As
New
Entity.User
5:
BlUser = DaUser.Check(User)
6:
If
BlUser.User_Pwd = User.User_Pwd
Then
7:
Return
True
8:
Else
9:
Return
False
10:
End
If
11:
End
Function
12:
End
Class
數據持久層
1:
Imports
System.Data.SqlClient
2:
Public
Class
D_UserInfo
3:
Dim
ConnStr
As
String
=
"Data Source=******;Initial Catalog=Student;User ID=sa;Password=******"
4:
Dim
conn
As
SqlConnection =
New
SqlConnection(ConnStr)
5:
Function
Check(
ByVal
User
As
Entity.User)
As
Entity.User
6:
Dim
sql
As
String
=
"select * from UserInfo where UserInfo="
& User.User_ID
7:
Dim
cmd
As
SqlCommand =
New
SqlCommand(sql, conn)
8:
Dim
read
As
SqlDataReader
9:
Try
10:
conn.Open()
11:
read = cmd.ExecuteReader
12:
User.User_ID = read.Item(0)
13:
User.User_Pwd = read.Item(1)
14:
Return
User
15:
Catch
ex
As
Exception
16:
User.User_Pwd =
""
17:
Return
User
18:
End
Try
19:
End
Function
20:
End
Class
2. 簡單工廠
添加一個工廠類和一個接口
接口類
1:
Public
Interface
IUserInfo
2:
Function
Check(
ByVal
IUser
As
Entity.User)
As
Entity.User
3:
End
Interface
工廠類
1:
Imports
[
Interface
]
2:
Public
Class
DFactory
3:
'Dim DataBase As String = "Access"
4:
Dim
DataBase
As
String
=
"Sql"
5:
Function
CreateUserInfo()
As
IUserInfo
6:
Dim
DB
As
IUserInfo
7:
Select
Case
DataBase
8:
Case
"Sql"
9:
DB =
New
D_UserInfoSql
10:
'Case "Access"
11:
' DB = New D_UserInfoAccess
12:
End
Select
13:
Return
DB
14:
End
Function
15:
End
Class
當然 D_UserInfoSql 實現接口,代碼基本不變
當有新的數據庫使用時候(例如 Access 數據庫)可以將工廠中的注釋部分添上,然后重新寫 Dal 層就可以直接使用,但是這樣的不足是還是需要再次編譯工廠,利用反射可以解決這個問題。
3. 抽象工廠加反射
工廠類
1:
Imports
[
Interface
]
2:
Imports
System.Reflection
3:
Public
Class
DFactory
4:
'抽象工廠加反射
5:
Dim
DBString
As
String
= System.Configuration.ConfigurationSettings.AppSettings(
"DBString"
)
6:
Function
CreateUserInfo()
As
IUserInfo
7:
Return
CType
(
Assembly
.Load(
"DAL"
).CreateInstance(
"DAL.D_UserInfo"
& DBString), IUserInfo)
8:
End
Function
9:
End
Class
數據持久層
1:
Imports
System.Data.SqlClient
2:
Public
Class
D_UserInfoSql :
Implements
[
Interface
].IUserInfo
3:
'Dim ConnStr As String = "Data Source=******;Initial Catalog=Student;User ID=sa;Password=******"
4:
Dim
ConnStr
As
String
= System.Configuration.ConfigurationSettings.AppSettings(
"ConnStr"
)
5:
Dim
conn
As
SqlConnection =
New
SqlConnection(ConnStr)
6:
Public
Function
Check(
ByVal
IUser
As
Entity.User)
As
Entity.User
Implements
[
Interface
].IUserInfo.Check
7:
Dim
sql
As
String
=
"select * from UserInfo where UserInfo="
& IUser.User_ID
8:
Dim
cmd
As
SqlCommand =
New
SqlCommand(sql, conn)
9:
Dim
read
As
SqlDataReader
10:
Try
11:
conn.Open()
12:
read = cmd.ExecuteReader
13:
IUser.User_ID = read.Item(0)
14:
IUser.User_Pwd = read.Item(1)
15:
Return
IUser
16:
Catch
ex
As
Exception
17:
IUser.User_Pwd =
""
18:
Return
IUser
19:
End
Try
20:
End
Function
21:
End
Class
配置文件
1:
<
appSettings
>
2:
<
add
key
="ConnStr"
value
="Data Source=******;Initial Catalog=Student;User ID=sa;Password=******"
></
add
>
3:
<
add
key
="DBString"
value
="Sql"
></
add
>
4:
</
appSettings
>
添加兩個 Key ,一個是連接數據庫的字符串,一個是通過反射來產生不同數據庫的 Dal 層的
這樣一來就可以實現設計模式中的“開閉原則”,如果更換數據庫只需要增加類(DAL),而不需要更改,更不需要重新編譯。
PS : 配置文件必須在界面層
1、 反射的寫法 :
objType=Assembly.Load(AssemblyPath).CreateInstance(className); 其中: AssemblyPath 指程序集名。 className 指命名空間 . 類名稱。
2、 反射的一個原則 : 一切皆以 UI 層的 bin 文件夾中的 dll 名稱為中心。 ( 原因很簡單 :.net 類加載的機制就是默認從本程序集的 bin 文件中找 , 所以 bin 文件夾中一定要有要加載的程序集的 dll) 。 UI 層中 bin 文件夾中 dll 叫什么名字 AssemblyPath 就使用什么名字 ,bin 內部類的全名叫什么, className 就寫成什么全名。 .net 中的引用 : 加入對某個程序集的引用就能在程序集有變化時自動拷貝 dll 。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

