关于工厂模式的数据库组件的反编译解读

工厂模式:

GOF:定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。
简单就来就是你放什么菜入锅,加入油盐酱醋就会端上来什么菜来。

现在,由于对将来可能出现的数据移植问题而产生的数据库连接以及相关类的引用(如sql server应引用System.Data.SqlClient; Oracle应引用System.Data.OracleClient;当然还有直接用OleDB对象的。这时候数据移植产生了巨大的代码变更。
我们需要做的,就是公开出一个统一的接口,传入datasource后,自动在组件里进行处理并给出适合这种类的方法。我们可以用到工厂方法模式。

我们项目现在引入了一个非常简单并且非常典型的数据组件,我用Reflector反编译了一下,代码写得也没有什么意外的。

公开的接口为DataBase,并定义了以下方法(当然这些方法目前为止是不够D)
public interface Database
{
      // Methods
      DataTable GetDatabyStoredProc(string procName, object[] prams);
      DataTable GetDataTableFromSQL(string sql);
      int GetDataTableFromSQL(string sql, int startRecord, int maxRecords, ref DataSet ds);
      object GetSingleValue(string sql);
      int RunSQL(string sql);
      int RunStoredProc(string procName, object[] prams);
}

其下分别有三个派生类:OleDB,Oracle,SqlServer,且分别实现了接口中的方法。
并包含了自身的私有方法:如open(),close(),以及connStr,conn等属性。

此外,组件中还定义了一个public的类:DataAccess;此类只有一个方法
public static Database DatabaseCreate(string DataSourceName);

传入数据源的名称,并根据此名称,使用类的私有方法private static DataAccess.DBLink GetDBLink(string DataSourceName)
来返回对应的派生类的实例化对象;不难相象GetDBLink()方法无非是一些switch之类的,根据数据源名判断数据库类型之类的代码。
当然,我们也可以统一在一个xml配置文件里进行统一配置,而无需对代码本身进行任何修改。

附:


public class DataAccess
{
      
// Methods
      public DataAccess();
      
public static Database DatabaseCreate(string which);
      
private static DBLink GetDBLink(string which);

      
// Nested Types
      public class DBLink
      
{
            
// Methods
            public DBLink(string sKey);

            
// Properties
            public string DbKey getset; }
            
public string DbString getset; }
            
public int DbType getset; }

            
// Fields
            private string _DbKey;
            
private string _DbString;
            
private int _DbType;
      }


      
private enum DbProduct
      
{
            
// Fields
            OleDb = 2,
            Oracle 
= 0,
            SqlServer 
= 1
      }

}

判断具体实现什么派生类:
public DBLink(string sKey)
{
      
string text1;
      
if ((text1 = sKey) != null)
      
{
            text1 
= string.IsInterned(text1);
            
if (text1 == "DataSrcName")
            
{
                  
this.DbKey = "DataSrcName";
                  
this.DbType = Convert.ToInt32(DataAccess.DbProduct.Oracle);
                  
this.DbString = "Password=; User ID=; Data Source=DataSrcName";
                  
return;
            }

      }

      
this.DbKey = "Public";
      
this.DbType = Convert.ToInt32(DataAccess.DbProduct.Oracle);
      
this.DbString = "Password=; User ID=; Data Source=DataSrcName";
}
 
posted @ 2005-09-14 20:54  Elaine Shi  阅读(532)  评论(1编辑  收藏  举报