|
|
|
| 您的位置:首页>>设计模式>>从一个ConnectionPool的实现看Designnbsp;Pattern的运用nbsp;(三) |
|
|
从一个ConnectionPool的实现看Designnbsp;Pattern的运用nbsp;(三)
|
| 2007-04-13 来源:www.javaresearch.org 作者:未知 |
从一个ConnectionPool的实现看Design Pattern的运用 (三)
作者;ajoo
根据上回对PooledConnection的分析,下面是对一个可重用PooledConnection的实现: public class PooledConnection implements Connection { public interface Pool { //引入这个interface, 是因为我们的PooledConnection只需要知道如何返还Connection。 //本着接口最小化原则,我们只定义我们需要的操作。 void closeConnection(Connection conn); }
private interface ConnectionState { //state pattern的interface. public ConnectionState close() throws SQLException; //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<maxClients 生成一个新的连接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大业。
|
|
|
| |