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

系统 1412 0

注意:文中代码有误,为保留历史痕迹在本文不做修改,正确代码详 见《 纠错

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

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

经典的三层架构

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
        
      
<style type="text/css"> <!-- .csharpcode, .csharpcode pre {font-size:small; color:black; font-family:consolas,"Courier New",courier,monospace; background-color:#ffffff} .csharpcode pre {margin:0em} .csharpcode .rem {color:#008000} .csharpcode .kwrd {color:#0000ff} .csharpcode .str {color:#006080} .csharpcode .op {color:#0000c0} .csharpcode .preproc {color:#cc6633} .csharpcode .asp {background-color:#ffff00} .csharpcode .html {color:#800000} .csharpcode .attr {color:#ff0000} .csharpcode .alt {background-color:#f4f4f4; width:100%; margin:0em} .csharpcode .lnum {color:#606060} --> </style> <style type="text/css"> <!-- .csharpcode, .csharpcode pre {font-size:small; color:black; font-family:consolas,"Courier New",courier,monospace; background-color:#ffffff} .csharpcode pre {margin:0em} .csharpcode .rem {color:#008000} .csharpcode .kwrd {color:#0000ff} .csharpcode .str {color:#006080} .csharpcode .op {color:#0000c0} .csharpcode .preproc {color:#cc6633} .csharpcode .asp {background-color:#ffff00} .csharpcode .html {color:#800000} .csharpcode .attr {color:#ff0000} .csharpcode .alt {background-color:#f4f4f4; width:100%; margin:0em} .csharpcode .lnum {color:#606060} --> </style> <style type="text/css"> <!-- .csharpcode, .csharpcode pre {font-size:small; color:black; font-family:consolas,"Courier New",courier,monospace; background-color:#ffffff} .csharpcode pre {margin:0em} .csharpcode .rem {color:#008000} .csharpcode .kwrd {color:#0000ff} .csharpcode .str {color:#006080} .csharpcode .op {color:#0000c0} .csharpcode .preproc {color:#cc6633} .csharpcode .asp {background-color:#ffff00} .csharpcode .html {color:#800000} .csharpcode .attr {color:#ff0000} .csharpcode .alt {background-color:#f4f4f4; width:100%; margin:0em} .csharpcode .lnum {color:#606060} --> </style>

业务逻辑层

      
           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
    
<style type="text/css"> <!-- .csharpcode, .csharpcode pre {font-size:small; color:black; font-family:consolas,"Courier New",courier,monospace; background-color:#ffffff} .csharpcode pre {margin:0em} .csharpcode .rem {color:#008000} .csharpcode .kwrd {color:#0000ff} .csharpcode .str {color:#006080} .csharpcode .op {color:#0000c0} .csharpcode .preproc {color:#cc6633} .csharpcode .asp {background-color:#ffff00} .csharpcode .html {color:#800000} .csharpcode .attr {color:#ff0000} .csharpcode .alt {background-color:#f4f4f4; width:100%; margin:0em} .csharpcode .lnum {color:#606060} --> </style> <style type="text/css"> <!-- .csharpcode, .csharpcode pre {font-size:small; color:black; font-family:consolas,"Courier New",courier,monospace; background-color:#ffffff} .csharpcode pre {margin:0em} .csharpcode .rem {color:#008000} .csharpcode .kwrd {color:#0000ff} .csharpcode .str {color:#006080} .csharpcode .op {color:#0000c0} .csharpcode .preproc {color:#cc6633} .csharpcode .asp {background-color:#ffff00} .csharpcode .html {color:#800000} .csharpcode .attr {color:#ff0000} .csharpcode .alt {background-color:#f4f4f4; width:100%; margin:0em} .csharpcode .lnum {color:#606060} --> </style> <style type="text/css"> <!-- .csharpcode, .csharpcode pre {font-size:small; color:black; font-family:consolas,"Courier New",courier,monospace; background-color:#ffffff} .csharpcode pre {margin:0em} .csharpcode .rem {color:#008000} .csharpcode .kwrd {color:#0000ff} .csharpcode .str {color:#006080} .csharpcode .op {color:#0000c0} .csharpcode .preproc {color:#cc6633} .csharpcode .asp {background-color:#ffff00} .csharpcode .html {color:#800000} .csharpcode .attr {color:#ff0000} .csharpcode .alt {background-color:#f4f4f4; width:100%; margin:0em} .csharpcode .lnum {color:#606060} --> </style>

数据持久层

      
           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
      
    
<style type="text/css"> <!-- .csharpcode, .csharpcode pre {font-size:small; color:black; font-family:consolas,"Courier New",courier,monospace; background-color:#ffffff} .csharpcode pre {margin:0em} .csharpcode .rem {color:#008000} .csharpcode .kwrd {color:#0000ff} .csharpcode .str {color:#006080} .csharpcode .op {color:#0000c0} .csharpcode .preproc {color:#cc6633} .csharpcode .asp {background-color:#ffff00} .csharpcode .html {color:#800000} .csharpcode .attr {color:#ff0000} .csharpcode .alt {background-color:#f4f4f4; width:100%; margin:0em} .csharpcode .lnum {color:#606060} --> </style>

2. 简单工厂

image

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

接口类

      
           1:  
      
      
        Public
      
      
        Interface
      
       IUserInfo
    
      
           2:  
      
      
        Function
      
       Check(
      
        ByVal
      
       IUser 
      
        As
      
       Entity.User) 
      
        As
      
       Entity.User
    
      
           3:  
      
      
        End
      
      
        Interface
      
    
<style type="text/css"> <!-- .csharpcode, .csharpcode pre {font-size:small; color:black; font-family:consolas,"Courier New",courier,monospace; background-color:#ffffff} .csharpcode pre {margin:0em} .csharpcode .rem {color:#008000} .csharpcode .kwrd {color:#0000ff} .csharpcode .str {color:#006080} .csharpcode .op {color:#0000c0} .csharpcode .preproc {color:#cc6633} .csharpcode .asp {background-color:#ffff00} .csharpcode .html {color:#800000} .csharpcode .attr {color:#ff0000} .csharpcode .alt {background-color:#f4f4f4; width:100%; margin:0em} .csharpcode .lnum {color:#606060} --> </style> <style type="text/css"> <!-- .csharpcode, .csharpcode pre {font-size:small; color:black; font-family:consolas,"Courier New",courier,monospace; background-color:#ffffff} .csharpcode pre {margin:0em} .csharpcode .rem {color:#008000} .csharpcode .kwrd {color:#0000ff} .csharpcode .str {color:#006080} .csharpcode .op {color:#0000c0} .csharpcode .preproc {color:#cc6633} .csharpcode .asp {background-color:#ffff00} .csharpcode .html {color:#800000} .csharpcode .attr {color:#ff0000} .csharpcode .alt {background-color:#f4f4f4; width:100%; margin:0em} .csharpcode .lnum {color:#606060} --> </style>

工厂类

      
           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
      
    
<style type="text/css"> <!-- .csharpcode, .csharpcode pre {font-size:small; color:black; font-family:consolas,"Courier New",courier,monospace; background-color:#ffffff} .csharpcode pre {margin:0em} .csharpcode .rem {color:#008000} .csharpcode .kwrd {color:#0000ff} .csharpcode .str {color:#006080} .csharpcode .op {color:#0000c0} .csharpcode .preproc {color:#cc6633} .csharpcode .asp {background-color:#ffff00} .csharpcode .html {color:#800000} .csharpcode .attr {color:#ff0000} .csharpcode .alt {background-color:#f4f4f4; width:100%; margin:0em} .csharpcode .lnum {color:#606060} --> </style> <style type="text/css"> <!-- .csharpcode, .csharpcode pre {font-size:small; color:black; font-family:consolas,"Courier New",courier,monospace; background-color:#ffffff} .csharpcode pre {margin:0em} .csharpcode .rem {color:#008000} .csharpcode .kwrd {color:#0000ff} .csharpcode .str {color:#006080} .csharpcode .op {color:#0000c0} .csharpcode .preproc {color:#cc6633} .csharpcode .asp {background-color:#ffff00} .csharpcode .html {color:#800000} .csharpcode .attr {color:#ff0000} .csharpcode .alt {background-color:#f4f4f4; width:100%; margin:0em} .csharpcode .lnum {color:#606060} --> </style>

当然 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
      
    
<style type="text/css"> <!-- .csharpcode, .csharpcode pre {font-size:small; color:black; font-family:consolas,"Courier New",courier,monospace; background-color:#ffffff} .csharpcode pre {margin:0em} .csharpcode .rem {color:#008000} .csharpcode .kwrd {color:#0000ff} .csharpcode .str {color:#006080} .csharpcode .op {color:#0000c0} .csharpcode .preproc {color:#cc6633} .csharpcode .asp {background-color:#ffff00} .csharpcode .html {color:#800000} .csharpcode .attr {color:#ff0000} .csharpcode .alt {background-color:#f4f4f4; width:100%; margin:0em} .csharpcode .lnum {color:#606060} --> </style>

数据持久层

      
           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
      
    
<style type="text/css"> <!-- .csharpcode, .csharpcode pre {font-size:small; color:black; font-family:consolas,"Courier New",courier,monospace; background-color:#ffffff} .csharpcode pre {margin:0em} .csharpcode .rem {color:#008000} .csharpcode .kwrd {color:#0000ff} .csharpcode .str {color:#006080} .csharpcode .op {color:#0000c0} .csharpcode .preproc {color:#cc6633} .csharpcode .asp {background-color:#ffff00} .csharpcode .html {color:#800000} .csharpcode .attr {color:#ff0000} .csharpcode .alt {background-color:#f4f4f4; width:100%; margin:0em} .csharpcode .lnum {color:#606060} --> </style>

配置文件

      
           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
      
      
        >
      
    
<style type="text/css"> <!-- .csharpcode, .csharpcode pre {font-size:small; color:black; font-family:consolas,"Courier New",courier,monospace; background-color:#ffffff} .csharpcode pre {margin:0em} .csharpcode .rem {color:#008000} .csharpcode .kwrd {color:#0000ff} .csharpcode .str {color:#006080} .csharpcode .op {color:#0000c0} .csharpcode .preproc {color:#cc6633} .csharpcode .asp {background-color:#ffff00} .csharpcode .html {color:#800000} .csharpcode .attr {color:#ff0000} .csharpcode .alt {background-color:#f4f4f4; width:100%; margin:0em} .csharpcode .lnum {color:#606060} --> </style>

添加两个 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元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论