Decorator Pattern

本文通过实现一个简单的连接池,并运用装饰模式确保连接能够被正确地归还到连接池中,而非直接关闭,展示了装饰模式如何增强对象的功能而不改变其接口。
装饰模式是以对客户端透明的方式扩展对象的功能。是继承的替代方案。


UML图
[img]http://www.iteye.com/upload/attachment/141087/b708878b-e7fc-3217-929c-9dc8e721eb15.jpg[/img]
参照夏昕的hibernate书中的连接池例子,来了解装饰模式如何应用。

先新建一个连接池接口。
ConnectionPool.java
package com.javapatterns.decorator.jdbc;

import java.sql.Connection;

public interface ConnectionPool {
public Connection getConnection();
public void releaseConncetion(Connection conn) ;
}


新建一个连接池
DBConnectionPool.java
package com.javapatterns.decorator.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

public class DBConnectionPool implements ConnectionPool{

private Vector pool;
private Map stmtPool = new HashMap();
private static final int POOL_MAX_SIZE = 30;

public synchronized Connection getConnection() {
if(pool == null)
pool = new Vector();
Connection conn;
if (pool.isEmpty())
conn = createConnection();
else {
int last_idx = pool.size() - 1;
conn = (Connection)pool.get(last_idx);
pool.remove(last_idx);
}
return conn;
}

private Connection createConnection(){
Connection conn = null;
try {
Class.forName("org.gjt.mm.mysql.Driver");
conn = DriverManager.getConnection("dbc:mysql://localhost:3306/test","root","root");
return conn;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}

public void releaseConncetion(Connection conn) {
if (pool.size() > POOL_MAX_SIZE) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
else {
pool.add(conn);
}
}
}

DBConnectionPool是一个简陋的连接池,它有一个问题,当客户端调用Connection.close()关闭连接,而不是调用DBConnectionPool.releaseConncetion(Connection conn)返还Connection.这样会导致连接池彻底失效。

新建一个Dectorator
package com.javapatterns.decorator.jdbc;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.Map;

public class ConnectionDectorator implements Connection {
Connection conn;

public ConnectionDectorator(Connection conn) {
this.conn = conn;
}

public void clearWarnings() throws SQLException {
this.conn.clearWarnings();
}

public void close() throws SQLException {
this.conn.close();
}

public void commit() throws SQLException {
this.conn.commit();
}

public Statement createStatement() throws SQLException {
return this.conn.createStatement();
}

public Statement createStatement(int resultSetType, int resultSetConcurrency)
throws SQLException {
return this.conn.createStatement(resultSetType, resultSetConcurrency);
}

public Statement createStatement(int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
return this.conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
}

public boolean getAutoCommit() throws SQLException {
return this.conn.getAutoCommit();
}

public String getCatalog() throws SQLException {
return this.conn.getCatalog();
}

public int getHoldability() throws SQLException {
return this.conn.getHoldability();
}

public DatabaseMetaData getMetaData() throws SQLException {
return this.conn.getMetaData();
}

public int getTransactionIsolation() throws SQLException {
return this.conn.getTransactionIsolation();
}

public Map getTypeMap() throws SQLException {
return this.conn.getTypeMap();
}

public SQLWarning getWarnings() throws SQLException {
return this.conn.getWarnings();
}

public boolean isClosed() throws SQLException {
return this.conn.isClosed();
}

public boolean isReadOnly() throws SQLException {
return this.conn.isReadOnly();
}

public String nativeSQL(String sql) throws SQLException {
return this.conn.nativeSQL(sql);
}

public CallableStatement prepareCall(String sql) throws SQLException {
return this.conn.prepareCall(sql);
}

public CallableStatement prepareCall(String sql, int resultSetType,
int resultSetConcurrency) throws SQLException {
return this.conn.prepareCall(sql, resultSetType, resultSetConcurrency);
}

public CallableStatement prepareCall(String sql, int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
return this.conn.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
}

public PreparedStatement prepareStatement(String sql) throws SQLException {
return this.conn.prepareStatement(sql);
}

public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
throws SQLException {
return this.conn.prepareStatement(sql, autoGeneratedKeys);
}

public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
throws SQLException {
return this.conn.prepareStatement(sql, columnIndexes);
}

public PreparedStatement prepareStatement(String sql, String[] columnNames)
throws SQLException {
return this.conn.prepareStatement(sql, columnNames);
}

public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency) throws SQLException {
return this.conn.prepareStatement(sql, resultSetType, resultSetConcurrency);
}

public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
return this.conn.prepareStatement(sql, resultSetType, resultSetConcurrency);
}

public void releaseSavepoint(Savepoint savepoint) throws SQLException {
this.conn.releaseSavepoint(savepoint);
}

public void rollback() throws SQLException {
this.conn.rollback();

}

public void rollback(Savepoint savepoint) throws SQLException {
this.conn.rollback(savepoint);
}

public void setAutoCommit(boolean autoCommit) throws SQLException {
this.conn.setAutoCommit(autoCommit);
}

public void setCatalog(String catalog) throws SQLException {
this.conn.setCatalog(catalog);
}

public void setHoldability(int holdability) throws SQLException {
this.conn.setHoldability(holdability);
}

public void setReadOnly(boolean readOnly) throws SQLException {
this.conn.setReadOnly(readOnly);
}

public Savepoint setSavepoint() throws SQLException {
return this.conn.setSavepoint();
}

public Savepoint setSavepoint(String name) throws SQLException {
return this.conn.setSavepoint(name);
}

public void setTransactionIsolation(int level) throws SQLException {
this.conn.setTransactionIsolation(level);
}

public void setTypeMap(Map arg0) throws SQLException {
this.conn.setTypeMap(arg0);
}

}



新建一个Concrete Decorator
package com.javapatterns.decorator.jdbc;

import java.sql.Connection;
import java.sql.SQLException;

public class PooledConnection extends ConnectionDectorator {
private ConnectionPool pool;

public PooledConnection(ConnectionPool pool, Connection conn) {
super(conn);
this.pool = pool;
}

@Override
public void close() throws SQLException {
pool.releaseConncetion(conn);
}
}



修改DBConnectionPool
package com.javapatterns.decorator.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

public class DBConnectionPool implements ConnectionPool{

private Vector pool;
private Map stmtPool = new HashMap();
private static final int POOL_MAX_SIZE = 30;

public synchronized Connection getConnection() {
if(pool == null)
pool = new Vector();
Connection conn;
if (pool.isEmpty())
conn = createConnection();
else {
int last_idx = pool.size() - 1;
conn = (Connection)pool.get(last_idx);
pool.remove(last_idx);
}
//decorator implementation
return new PooledConnection(this, conn);
}
...
}


当有多个Concrete Decorator类动态组合时,更能体现装饰模式的威力。当然,这里用动态代理代码会更简洁一些。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值