Factory設計模式
含義:定義一個(gè)用于創(chuàng )建對象的接口,讓子類(lèi)決定實(shí)例化哪一個(gè)類(lèi)。Factory Method使一個(gè)類(lèi)的實(shí)例化延遲到其子類(lèi)。我們這里可能會(huì )處理對多種數據庫的操作,因此,需要首先定義一個(gè)操縱數據庫的接口,然后,根據數據庫的不同,由類(lèi)工廠(chǎng)決定實(shí)例化哪個(gè)類(lèi)。
下面,我們首先來(lái)定義這個(gè)訪(fǎng)問(wèn)接口。為了方便說(shuō)明問(wèn)題,我們?yōu)檫@個(gè)類(lèi)定義了比較少的方法,其他的方法是很容易參照添加的。同時(shí)注意,我這里使用了abstract class來(lái)定義這個(gè)訪(fǎng)問(wèn)接口,而不是interface,理由在后面可以看到。
定義一個(gè)抽象類(lèi):
public abstract class DBOperator
{
public abstract IDbConnection Connection{get;} //得到數據庫連接
public abstract void Open(); //打開(kāi)數據庫連接
public abstract void Close(); //關(guān)閉數據庫連接
public abstract void BeginTrans(); //開(kāi)始一個(gè)事務(wù)
public abstract void CommitTrans(); //提交一個(gè)事務(wù)
public abstract void RollbackTrans(); //回滾一個(gè)事務(wù)
public abstract void exeSql(string strSql,string[] strParams,object[] objValues);
//執行Sql語(yǔ)句,沒(méi)有返回值
public abstract DataSet exeSqlForDataSet(string QueryString);
//執行Sql,返回DataSet
}
我們編寫(xiě)數據訪(fǎng)問(wèn)的具體實(shí)現類(lèi):
Sql Server的數據庫訪(fǎng)問(wèn)類(lèi):
internal class SqlDBOperator: DBOperator
{
private SqlConnection conn;
//數據庫連接
private SqlTransaction trans;
//事務(wù)處理類(lèi)
private bool inTransaction=false;
//指示當前是否正處于事務(wù)中
public override IDbConnection Connection
{
get{
return this.conn;
}
}
//SQL數據庫的連接方法
public SqlDBOperator(string strConnection)
{
this.conn= new SqlConnection(strConnection);
}
//打開(kāi)數據連接
public override void Open()
{
if(conn.State.ToString().ToUpper()!="OPEN")
this.conn.Open();
}
//關(guān)閉數據連接
public override void Close()
{
if (conn.State.ToString().ToUpper()=="OPEN")
this.conn.Close();
}
//打開(kāi)事務(wù)處理機制
public override void BeginTrans()
{
trans=conn.BeginTransaction() ;
inTransaction=true;
}
//提交事務(wù)處理機制
public override void CommitTrans()
{
trans.Commit();
inTransaction=false;
}
//回滾事務(wù)處理機制
public override void RollbackTrans()
{
trans.Rollback();
inTransaction=false;
}
//執行SQL語(yǔ)句的操作,無(wú)返回值
public override void exeSql(string strSql,string[] strParams,object[] strValues)
{
SqlCommand cmd=new SqlCommand();
cmd.Connection=this.conn ;
if(inTransaction)
cmd.Transaction=trans;
if((strParams!=null)&&(strParams.Length!=strValues.Length) )
throw new ParamValueNotMatchException("查詢(xún)參數和值不對應!");
cmd.CommandText=strSql;
if(strParams!=null)
{
for(int i=0;i<strParams.Length;i++)
cmd.Parameters.Add(strParams[i],strValues[i]);
}
cmd.ExecuteNonQuery();
}
//重載執行SQL語(yǔ)句的操作,返回數據集
public override DataSet exeSqlForDataSet(string QueryString)
{
SqlCommand cmd=new SqlCommand();
cmd.Connection=this.conn ;
if(inTransaction)
cmd.Transaction=trans;
DataSet ds = new DataSet();
SqlDataAdapter ad = new SqlDataAdapter();
cmd.CommandText=QueryString;
ad.SelectCommand =cmd;
ad.Fill(ds);
return ds;
}
}
Oledb的數據庫訪(fǎng)問(wèn)類(lèi):
internal class OleDBOperator : DBOperator
{
private OleDbConnection conn;
private OleDbTransaction trans;
private bool inTransaction=false;
public OleDBOperator(string strConnection)
{
this.conn= new OleDbConnection(strConnection);
}
public override IDbConnection Connection
{
get
{
return this.conn;
}
}
public override void Open()
{
if(conn.State.ToString().ToUpper()!="OPEN")
this.conn.Open();
}
public override void Close()
{
if (conn.State.ToString().ToUpper()=="OPEN")
this.conn.Close();
}
public override void BeginTrans()
{
trans=conn.BeginTransaction() ;
inTransaction=true;
}
public override void CommitTrans()
{
trans.Commit();
inTransaction=false;
}
public override void RollbackTrans()
{
trans.Rollback();
inTransaction=false;
}
public override void exeSql(string strSql,string[] strParams,object[] strValues)
{
OleDbCommand cmd=new OleDbCommand();
cmd.Connection=this.conn ;
if(inTransaction)
cmd.Transaction=trans;
if((strParams!=null)&&(strParams.Length!=strValues.Length) )
throw new ParamValueNotMatchException("查詢(xún)參數和值不對應!");
cmd.CommandText=this.ChangeQueryString(strSql);
if(strParams!=null)
{
for(int i=0;i<strParams.Length;i++)
cmd.Parameters.Add(strParams[i],strValues[i]);
}
cmd.ExecuteNonQuery();
}
public override DataSet exeSqlForDataSet(string QueryString)
{
OleDbCommand cmd=new OleDbCommand();
cmd.Connection=this.conn ;
if(inTransaction)
cmd.Transaction=trans;
DataSet ds = new DataSet();
OleDbDataAdapter ad = new OleDbDataAdapter();
cmd.CommandText=QueryString;
ad.SelectCommand =cmd;
ad.Fill(ds);
return ds;
}
}
我們需要創(chuàng )建一個(gè)Factory類(lèi),來(lái)實(shí)現自動(dòng)數據庫切換的管理。這個(gè)類(lèi)很簡(jiǎn)單,主要的功能就是根據數據庫連接字符串,判斷使用什么數據庫,然后,返回適當的數據庫操縱類(lèi)。在這里,判斷的方法很簡(jiǎn)單,只是根據兩種數據庫連接字符串的不同來(lái)判斷。在實(shí)際中,隨著(zhù)數據庫類(lèi)的增加,判斷的方法可能會(huì )有所變化。
public class DBOperatorFactory
{
public static DBOperator GetDBOperator(string strConnection)
{
if(strConnection.IndexOf("provider=")<0) //SqlServer
{
return new SqlDBOperator(strConnection);
}
else //other database
{
return new OleDBOperator(strConnection);
}
}
}
客戶(hù)端在代碼調用的時(shí)候,可能就是采用如下形式:
DBOperator db=DBOperatorFactory.GetDBOperator(strConnection)
db.Open();
db.需要的操作
db.Close();
或者:
DBOperator db=DBOperatorFactory.GetDBOperator(strConnection)
db.Open();db.BeginTrans();
try
{
db.需要的操作
db.CommitTrans();
}
catch
{
db.RollbackTrans();
}
db.Close();
當數據庫發(fā)生變化的時(shí)候,DBOperatorFactory會(huì )根據數據庫連接字符串自動(dòng)調用相應的類(lèi),客戶(hù)端不會(huì )感覺(jué)到變化,也不用去關(guān)心。這樣,實(shí)現了良好的封裝性。當然,前提是,你在編寫(xiě)程序的時(shí)候,沒(méi)有用到特定數據庫的特性,例如,Sql Server的專(zhuān)用函數。
實(shí)際上,Factory模式也可以不使用Factory類(lèi)來(lái)實(shí)現,而是讓接口抽象類(lèi)自己來(lái)管理,這可以稱(chēng)作自管理的Factory,是Factory模式的一種變形。這么做的好處,是可以免去一個(gè)Factory類(lèi),使代碼更加簡(jiǎn)練。這么做,我們需要對DBOperator類(lèi)做一些改變,增加一個(gè)Instance方法。這也是對DBOperator采用抽象類(lèi)而不是接口的原因(接口的方法不能有實(shí)現),代碼如下:
public static DBOperator Instance(string strConnection)
{
if(strConnection.IndexOf("provider=")<0) //SqlServer
{
return new SqlDBOperator(strConnection);
}
else //other database
{
return new OleDBOperator(strConnection);
}
}
然后,客戶(hù)端代碼就可能是類(lèi)似于下面的形式:
DBOperator db= DBOperator.Instance(strConnection)
db.Open();
db.需要的操作
db.Close();
Singleton設計模式
含義:保證一個(gè)類(lèi)僅有一個(gè)實(shí)例,并提供一個(gè)訪(fǎng)問(wèn)它的全局訪(fǎng)問(wèn)點(diǎn)。推而廣之,當我們需要精確控制類(lèi)在系統中的實(shí)例的個(gè)數的時(shí)候,就可以使用Singleton模式?,F在,我們需要構建一個(gè)緩沖池,保存數據庫類(lèi)的實(shí)例,正好是Singleton模式發(fā)揮作用的時(shí)候
我們仍然讓DBOperator類(lèi)自己來(lái)管理這個(gè)緩沖池,為了實(shí)現這個(gè)目的,我們需要對DBOperator類(lèi)做一些變化:
首先,增加兩個(gè)變量:
static DBOperator[] ConnectionPool=new DBOperator[int.Parse ConfigurationSettings.AppSettings["PoolCount"])];
static int CurrentPosition=-1;
然后,對Instance方法做一些改變:
public static DBOperator Instance(string strConnection)
{
if(ApplicationConfiguration.PooledConnectionCount<1) //沒(méi)有緩沖
{
return CreateNewDBOperator(strConnection);
}
else
{
CurrentPosition++;
if(CurrentPosition==ApplicationConfiguration.PooledConnectionCount)
CurrentPosition=0;
if(ConnectionPool[CurrentPosition]==null)
{
ConnectionPool[CurrentPosition]=CreateNewDBOperator(strConnection);
}
return ConnectionPool[CurrentPosition];
}
}
private static DBOperator CreateNewDBOperator(string strConnection)
{
if(strConnection.IndexOf("provider=")<0) //SqlServer
{
return new SqlDBOperator(strConnection);
}
else //other database
{
return new OleDBOperator(strConnection);
}
}
以上這些內容不是本人創(chuàng )作,是借見(jiàn)前輩的開(kāi)發(fā)思想整理出來(lái)的。本人學(xué)得好用,就放在自己的頁(yè)面上。
聯(lián)系客服