• 三层架构之抽象工厂加反射——实现数据库转换


    在做系统的时候有意识的用到了抽象工厂这个设计模式,主要解决的是数据库更换的问题。

    下面就以简单的登录来逐步的分析一下这个模式。

    经典的三层架构

    image

    数据库如下

    image

    1.      一般的数据库连接方式

    界面层

    image

     
       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.User_ID=User.ID
       6:          BlUser = DaUser.Check(BlUser)    
       7:            If BlUser.User_Pwd = User.User_Pwd Then
       8:               Return True
       9:           Else
      10:                Return False
      11:           End If
      12:        End Function
      13:  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.      简单工厂

    image

    添加一个工厂类和一个接口

    接口类

       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.抽象工厂加反射

    image

    工厂类

       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

    原创文章,转载请注明出处:http://www.cnblogs.com/beijiguangyong/
  • 相关阅读:
    tableView操作数据持久化
    9.0banb以前和9.0以后版本后JSON解析
    数据持久化存储回顾
    解决Xcode会出现的问题
    iview-cli 项目、iView admin 代理与跨域问题解决方案
    将变量做为一个对象的key,push新增进一个数组
    页面加载速度优化的建议
    vue中渲染页面,动态设置颜色
    e.currentTarget与e.target
    iview中tree的事件运用
  • 原文地址:https://www.cnblogs.com/beijiguangyong/p/2302780.html
Copyright © 2020-2023  润新知