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