首页 > 代码库 > 谈一谈:抽象工厂+反射+配置文件 实现数据访问程序

谈一谈:抽象工厂+反射+配置文件 实现数据访问程序

       《大话设计模式》中第15章中《就不能不换DB吗?》引出了我今天要谈论的主题:抽象工厂+反射+配置文件 实现数据访问程序。当时也不甚理解啊!到了机房收费的亲身实践中,终于体会到了这对组合的奥秘。


抽象工厂模式(Abstract Factory)

提供一个创建一系列相关或相互依赖对象的接口,而无需制定它们具体的类。知道它是用来创建工厂的就OK了。

反射

提供了封装程序集、模块和类型的对象。这里仅仅用到反射的一部分功能。且记住它的格式:  

Assembly.Load(“程序集名称” CreateInstance(“命名空间 类名称”)

配置文件 

存在于UI层,名字为App.config ,在程序打包发布后,仍可以从安装包中找到该文件并加以更改。(其它不再赘述)


按照大鸟的思路,这种组合写法就能够方便的更改DB,在程序需要更改数据库时不需要重新返工,只需要从配置文件中,把数据库的名字更改一下就Ok了。我把大鸟的思路写一下。(《大话》中的代码是用C#语言写的,而我是在vb.net 版的机房收费系统中理顺思路的,所以以下代码均为vb.net 代码,大同小异)

Factory 中 DataAccess类

<span style="font-size:18px;">Imports System.Configuration    '配置文件命名空间  
Imports System.Reflection       '添加对反射的引用 
Public Class DataAccess
    '程序集名称(同时代表命名空间名称):DAL  
    Dim AssemblyName As String = System.Configuration.ConfigurationManager.AppSettings("assName")
    '数据库类型:Sql  
    Dim db As String = System.Configuration.ConfigurationManager.AppSettings("DB")
    '创建D层类SqlUserInfoDAL的实例  
    Public Function CreateUserInfo() As IDAL.IUserInfo
        Dim dalUserInfoName As String = AssemblyName & "." & db & "UserInfoDAL"        '要实例化的D层类的名称  
        Return CType(Assembly.Load(AssemblyName).CreateInstance(dalUserInfoName), IUserInfo)
    End Function
End Class</span>
配置文件中添加

<span style="font-size:18px;">      <appSettings> 
          <add key ="assName" value =http://www.mamicode.com/"DAL"/>>
        如果需要更改数据库比如说要把Sqlserver 更改为Access即可 (这就要求我们在D层建类时,严格命名,把Sql里的类名前面应该是Sqlserver开头,Access数据库时类名应该用Access开头。)如下图:



但是我在敲这一部分时,是这样写的(最初的最初,我没有想着要给系统更换数据库,所以某些变量和方法命名时没有考虑把数据库的选择表达出来)

Factory 中 DataAccess类

<span style="font-size:18px;">Imports System.Reflection    '添加对反射的引用
Imports System.Configuration  '添加对配置文件的引用
Public Class DataAccess
    Dim strDALName As String = System.Configuration.ConfigurationSettings.AppSettings("DALName")  '定义一个字符串strDALName,通过配置文件获取D层程序集的名称和命名空间的名称(一般情况下相同)并赋值给所声明的变量strDALName

    ' 创建一个用户User接口,并把对应的类名称关联上
    Public Function CreateIUser() As IDAL.IUser
        '通过配置文件和反射,实例化接口并能够通过更改配置文件的内容更改 实例化D层的程序集和命名空间下的类
        Return CType(Assembly.Load(strDALName).CreateInstance(strDALName + "." + "UserDAL"), IDAL.IUser)
    End Function
    ' 创建一个学生信息StudentInfo接口,并把对应类名称关联上
    Function CreateIStudent() As IDAL.IStudentInfo
        Return CType(Assembly.Load(strDALName).CreateInstance(strDALName + "." + "StudentInfoDAL"), IDAL.IStudentInfo)
    End Function
End Class</span>

配置文件中这样写的

<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
    
      <configSections>
      </configSections>
      <connectionStrings>
            <add name="UI.My.MySettings.MyChargeSystemConnectionString" connectionString="Data Source=(local);Initial Catalog=MyChargeSystem;User ID=sa;Password=123456"
                  providerName="System.Data.SqlClient" />
      </connectionStrings>
      <appSettings> 
          <add key="strConnection" value=http://www.mamicode.com/"Server=bao;DataBase=MyChargeSystem;User ID=sa;Password=123456"  />>
        大家只要关注:<add key ="DALName" value =http://www.mamicode.com/"SqlServerDAL"/> 这一行就可以了,把配置文件全部内容贴出来只是让大家了解配置文件内容的全貌。

        考虑到以后可能更换数据库,例如,日后我需要把现在所用的sqlserver 数据库更换为Access,我们只需要重新添加一个程序集即可。例如把该程序集命名为AccessDAL,紧接着,配置文件中把

<add key ="DALName" value =http://www.mamicode.com/"SqlServerDAL"/>

更改为

<add key ="DALName" value =http://www.mamicode.com/"AccessDAL"/>

        然后在里面添加其他类,类名和里面的方法还应用SqlServer 数据库时的类名和方法就可以了,而不需要更改程序的其他程序集(其他的层)。见下图


小结

        不管黑猫白猫,逮住老鼠就是好猫。解决问题的方法往往不局限于一种,我相信抽象工厂+反射+配置文件 这个组合不仅仅能更换一个数据库,还能解决其他的一些问题。这都需要我们对写程序有一种钻研和痴迷的精神,就像小菜最后说的:无痴迷,不成功。相信大家经过不懈的努力,都会成为优秀的程序员。

谈一谈:抽象工厂+反射+配置文件 实现数据访问程序