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

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

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

根據上回對PooledConnection的分析,下面是對一個可重用PooledConnection的實現:

 

public class PooledConnection implements Connection{

 

  public interface Pool{

  //引入這個interface, 是因為我們的PooledConnection只需要知道如何返還Connection. 本著介面最小化原則,我們只定義我們需要的操作。

    void closeConnection(Connection conn);

  }

 

  private interface ConnectionState{

  //state pattern的interface.

  ConnectionState close()

  throws Exception;

  //close()方法是唯一引起狀態轉移的方法。

  boolean isClosed();

  Connection getOpenConnection()

  throws SQLException;

  }

 

  private static class ClosedConnection implements ConnectionState{

  public final ConnectionState close(){return this;}

  //當一個Connection已經closed了的時候,它實際上已經死了。所有對它的操作,除了isClosed()和close(), 只產生異常。所以,一個closed的Connection, 它已經不需要儲存那個物理連線和對出身ConnectionPool的連線。而且因為所有的 closed connection的狀態都一樣,所以可以用singleton來節省。

 

  public final Connection getOpenConnection()

  throws SQLException{

  throw new SQLException("Connection closed");

  }

  public final boolean isClosed(){return true;}

  private ClosedConnection(){}

  private static final ConnectionState _instance = new ClosedConnection();

  static ConnectionState instance(Connection conn, Pool pool){return _instance;}

  }

 

  private static class OpenConnection implements ConnectionState{

    private final Pool pool;

  private final Connection conn;

  public final ConnectionState close(){

  //對一個open connection的關閉,會把原始資料庫連線返還到connection pool. 同時,該連線死亡。

  pool.closeConnection(conn);

  return ClosedConnection.instance(conn, pool);

  }

  public final Connection getOpenConnection()

  {return conn;}

   public final boolean isClosed(){return false;}

  OpenConnection(Connection conn, Pool pool){

    this.conn = conn; this.pool = pool;

  }

  static ConnectionState instance(Connection conn, Pool pool){

    return new OpenConnection(conn, pool);

  }

  }

  private ConnectionState state;

 

  //用靜態的工廠方法,可以隱藏我們的實現類,以後,根據需要,我們可以方便地修改實現類,比如用內部類取代。

//根據要修飾的Connection的狀態,初始化PooledConnection

  public static Connection decorate(Connection conn, Pool pool)

  throws SQLException{

  if(conn.isClosed()){

  return new PooledConnection(ClosedConnection.instance(conn, pool));

  }

  else{

  return new PooledConnection(OpenConnection.instance(conn, pool));

  }

  }

 

 

  private PooledConnection(ConnectionState state){

  this.state = state;

  } 

  public final boolean isClosed(){

  return state.isClosed();

  }

 

  public final void close()

  throws SQLException{

  state = state.close();

  }

  private final Connection getOpenConnection()

  throws SQLException

  {return state.getOpenConnection();}

 

  /*****然後,做委託****/

  public final Statement createStatement()

  throws SQLException{

  return getOpenConnection().createStatement();

  }

  public final void rollback()throws SQLException{

  getOpenConnection().rollback();

  }

//等等等等

}

 

 

好,再來看看ConnectionPoolImpl怎樣使用PooledConnection.

 

public class ConnectionPoolImpl implements ConnectionPool{

public synchronized Connection getConnection(){

  Connection ret;

    如果pool裡有Connection

從pool中去掉一個Connection conn;

clients++;

ret = conn;

    否則,如果clients

    生成一個新的連線conn

    clients++;

    ret = conn;

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

 

    //下面的這個匿名類實際上是個adapter pattern. J 

    return PooledConnection.decorate(ret,

new PooledConnection.Pool{

public void closeConnection(Connection conn){

ConnectionPoolImpl.this.closeConnection(conn);

}

}

  }

  //其他都和原來一樣

}

 

這樣,所有對ConnectionPool的實現,都可以在返回一個物理Connection之前,把它用PooledConnection封裝一下。如此,程式碼得到了重用。ConnectionPool的實現者可以把主要精力放在怎樣處理池的各種功能。而不是怎樣包裝Connection.

世界真美好!

 

 

不過。。。。。

 

萬一,李四忘了用PooledConnection包裝他的Connection怎麼辦?不會報錯,因為反正都是Connection型別。

 

“你也太杞人憂天了吧?他忘了揍他不就得了?”哎,保不齊呀!人不是機器,總有犯錯的時候,到時候揍他有啥用?還手疼呢。

 

同學們,今天的家庭作業是:想辦法讓李四的健忘症不會影響我們的ConnectionPool大業。


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

相關文章