從一個ConnectionPool的實現看design pattern的運用 (一) (轉)

worldblog發表於2007-12-12
從一個ConnectionPool的實現看design pattern的運用 (一) (轉)[@more@] 

從一個ConnectionPool的實現看design pattern的運用 ():namespace prefix = o ns = "urn:schemas--com::office" />

 

什麼是ConnectionPool? 我們知道,JC提供了..Connection interface, 供我們連線不同的資料來源。但是,因為與建立連線是一個很大的開銷,所以,我們可以把已開啟的資料庫連線快取在一個連線池中,供後續的 Connection使用。使用者使用完Connection後,再把它返還到連線池中。

對一個連線池,有許多功能上的考慮。

1.如是否設定一個最大連線數,以保證資料庫不會因同時過多的連線請求而癱瘓;

2.是否設定一個最小連線數,以保證任何時刻都至少有若干個連線可用;

3.是否設定一個最多的空閒連線數,空閒連線超過這個數的就關閉過多的連線;

4.當對一個連線的請求不能被滿足時,是否讓請求同步等待,還是直接返回一個錯誤。

5.怎樣保證公平性,也就是說,一個對連線的同步請求會在一定的時間內得到x響應,而不是被餓死。

6.連線池是用vector, list還是其他的什麼Collection來實現。

等等等等。

下面,讓我們來看看一個ConnectionPool的實現:

public class ConnectionPool{

  private final Vector pool = new Vector();

  private int clients;

  private int maxClients;

  其他的一些連線屬性如username, pass, dsn等等;

  public synchronized Connection getConnection(){

    如果pool裡有Connection

從pool中去掉一個Connection conn;

clients++;

return conn;

    否則,如果clients

    生成一個新的連線conn

    clients++;

    return conn;

    否則,wait(),直到pool中有空閒Connection   

  }

  public synchronized void closeConnection(Connection conn){

    pool.add(conn);

    clients--;

    notify();

  }

  public synchronized void clear(){

    for each connection in pool

    conn.close();

    pool.removeAllElements();

  }

}

 

好了,讓我們來看一看有沒有什麼可以改善的。

 

首先,象我們剛開始所說的,對ConnectionPool的實現有許多不同的考慮,這個類明顯只是一個相當簡單的實現。那麼,我們是不是應該根據我們前面列出的條條,逐條進行實現呢?

不,如果那樣,我們就犯了過度設計的錯誤。也許我們現在並不需要那麼複雜的功能,為什麼要自找麻煩呢?而且,有些功能的取捨,並不是簡單的好與壞,是要根據具體的需要變化的。有些人也許會說,好吧,我在類裡放一些布林變數,對每種功能是否支援都可以configure. 這樣也許可行,但,你還是要對每個功能寫程式碼,最後這個ConnectionPool就變成一個spaghetti了。而且,夥計,讓我們謙虛一點吧!“不是我不明白,這世界變化快”,我們得承認,我們永遠也不可能預測所有的可能性。也不可能把所有的需求都實現到一個類中去。

那麼,我還“首先”什麼呢?反正也是先實現簡單的,“Simple and Stupid”。就這樣不是挺好嗎?問題是,我們要考慮使用我們ConnectionPool得使用者。雖然需求可能變化多端,但我們還是應該儘可能給使用者提供一個固定的介面。你不能這樣要求使用你的ConnectionPool的員:“喂,哥們兒,我昨天寫了一個ConnectionPool2, 比ConnectionPool酷多了,你改用這個吧。Replace All就行了”。

因此,我們應該把ConnectionPool設計成一個interface, 這樣,無論實現類如何變化,使用ConnectionPool interface的使用者可以不受影響。他們甚至可以根據需要使用不同的ConnectionPool的實現。簡單,是嗎?不就是一個interface嘛。相信我,你會看到它的作用有多大的。

 

其次,一個好的ConnectionPool應該是對Connection的使用者透明的。對一個使用Connection interface 的使用者,如:

void doQuery(Connection conn){……}

它應該對該Connection是否來自ConnectionPool不敏感。

那麼,當不使用ConnectionPool時,我們怎麼釋放Connection呢?對了,是Connection.close(). 我們不應該要求使用者改調ConnectionPool.closeConnection來釋放Connection.

 

第三,假設我們有兩個ConnectionPool物件,一個連線資料庫,另一個連線. 現在,使用者同時使用兩個ConnectionPool, 當使用者使用完時,他不小心呼叫了sqlPool.closeConnection(orclConn); orclPool.closeConnection(sqlConn);

天啊!不定時炸彈!不要光埋怨程式設計師:“那種只知道依靠類庫的容錯性,沒有類庫的保護不知道怎麼的程式設計師不適合使用Java”。其實這完全是你的錯。

 

 

 

好了,預知後事如何,請聽下回分解。家庭作業是,請大家回去想想怎麼設計這個ConnectionPool。

 

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-991975/,如需轉載,請註明出處,否則將追究法律責任。

相關文章