装饰者设计模式
如果想要对某个对象的功能进行扩展时,就可以使用装饰者设计模式。
装饰者设计模式的使用方式:
- 编写一个类,实现与被包装类相同的接口。【就是说和你新建的装饰类要模仿别的一样 这里指的是 实现Connction接口 就模仿了JDBC的Connction接口.】
- 定义一个被包装类类型的变量。
- 定义构造方法,把被包装类的对象注入,给被包装类变量赋值。
- 对于不需要改写的方法,调用原有的方法。
- 对于需要改写的方法,写自己的代码。
目前的问题在于我们不希望Connection对象中的close方法关闭连接,而是希望去将连接返回到池中,这时就需要对Connection类进行包装。因为我们使用的Mysql数据库,所以这里面实际上是对com.mysql.jdbc.Connection的包装。根据上面的方式,来包装一下Connection类。
全代码: Util > DB.java:
package Util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DB {
private static String url = "jdbc:mysql://localhost:3306/jdbc";
private static String user = "root";
private static String pass = "root";
static {
// 连接数据库
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection GetConnction() {
try {
return DriverManager.getConnection(url, user, pass);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
package Util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DB {
private static String url = "jdbc:mysql://localhost:3306/jdbc";
private static String user = "root";
private static String pass = "root";
static {
// 连接数据库
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection GetConnction() {
try {
return DriverManager.getConnection(url, user, pass);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
然后我们包装一个自己的 Connction 主要重写Close方法:
MyCloseConnection > MyConntion.java:
package MyCloseConnection;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
public class MyConntion implements Connection{
private Connection mConn = null;
private LinkedList<Connection> mPool = null;
/***
* 构造函数
* @param mConn
* @param mPool
*/
public MyConntion(Connection mConn, LinkedList<Connection> mPool) {
this.mConn = mConn;
this.mPool = mPool;
}
/*----------------------------------------------------*/
//主要还得重写这个Close!!
@Override
public void close() throws SQLException {
this.mPool.add(mConn); //使用完 放回去
}
@Override
public boolean isWrapperFor(Class<?> arg0) throws SQLException {
return false;
}
@Override
public <T> T unwrap(Class<T> arg0) throws SQLException {
return null;
}
@Override
public void abort(Executor executor) throws SQLException {
}
@Override
public void clearWarnings() throws SQLException {
}
@Override
public void commit() throws SQLException {
}
@Override
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
return null;
}
@Override
public Blob createBlob() throws SQLException {
return null;
}
@Override
public Clob createClob() throws SQLException {
return null;
}
@Override
public NClob createNClob() throws SQLException {
return null;
}
@Override
public SQLXML createSQLXML() throws SQLException {
return null;
}
@Override
public Statement createStatement() throws SQLException {
return null;
}
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
return null;
}
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
return null;
}
@Override
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
return null;
}
@Override
public boolean getAutoCommit() throws SQLException {
return false;
}
@Override
public String getCatalog() throws SQLException {
return null;
}
@Override
public Properties getClientInfo() throws SQLException {
return null;
}
@Override
public String getClientInfo(String name) throws SQLException {
return null;
}
@Override
public int getHoldability() throws SQLException {
return 0;
}
@Override
public DatabaseMetaData getMetaData() throws SQLException {
return null;
}
@Override
public int getNetworkTimeout() throws SQLException {
return 0;
}
@Override
public String getSchema() throws SQLException {
return null;
}
@Override
public int getTransactionIsolation() throws SQLException {
return 0;
}
@Override
public Map<String, Class<?>> getTypeMap() throws SQLException {
return null;
}
@Override
public SQLWarning getWarnings() throws SQLException {
return null;
}
@Override
public boolean isClosed() throws SQLException {
return false;
}
@Override
public boolean isReadOnly() throws SQLException {
return false;
}
@Override
public boolean isValid(int timeout) throws SQLException {
return false;
}
@Override
public String nativeSQL(String sql) throws SQLException {
return null;
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
return null;
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return null;
}
@Override
public CallableStatement prepareCall(String sql) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
return null;
}
@Override
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
}
@Override
public void rollback() throws SQLException {
}
@Override
public void rollback(Savepoint savepoint) throws SQLException {
}
@Override
public void setAutoCommit(boolean autoCommit) throws SQLException {
}
@Override
public void setCatalog(String catalog) throws SQLException {
}
@Override
public void setClientInfo(Properties properties) throws SQLClientInfoException {
}
@Override
public void setClientInfo(String name, String value) throws SQLClientInfoException {
}
@Override
public void setHoldability(int holdability) throws SQLException {
}
@Override
public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
}
@Override
public void setReadOnly(boolean readOnly) throws SQLException {
}
@Override
public Savepoint setSavepoint() throws SQLException {
return null;
}
@Override
public Savepoint setSavepoint(String name) throws SQLException {
return null;
}
@Override
public void setSchema(String schema) throws SQLException {
}
@Override
public void setTransactionIsolation(int level) throws SQLException {
}
@Override
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
}
}
后面的代码用不到的你别去写即可。
然后我们新建一个连接池【规范的】:
ConnPool > Connpool.java
主要重写GetConntion 方法 ,返回的是自己包装过的【改写过Close的】, 那么就很完美了。
package ConnPool;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.logging.Logger;
import javax.sql.DataSource;
import MyCloseConnection.MyConntion;
import Util.DB;
public class Connpool implements DataSource{
private static LinkedList<Connection> pool = (LinkedList<Connection>) Collections.synchronizedList(new LinkedList<Connection>());
static {
//创建连接池 顺便解决线程不安全
for(int i = 0;i < 10;i++) {
Connection conn = DB.GetConnction();
if(conn != null) {
pool.add(conn);
}
}
//是否成功添加
System.out.println("数据库连接池初始化成功:" + pool.size() + "个");
}
/*------------------------------------------------------------------------*/
//主要重写这个GetConnection【无参的】 关键看这里! 因为取出是最关键的!
@Override
public Connection getConnection() throws SQLException {
if(pool.size() > 0) {
//在池中取出一个连接
Connection conn = pool.removeFirst();
//放入自己包装过的 Conntion中【这个包装过的 也是一个Connection ! 记住啊】
MyConntion myConntion = new MyConntion(conn, pool);
//返回我包装过的‘Connection’
return myConntion;
}else {
throw new ExceptionInInitializerError("服务器繁忙,请稍后重试");
}
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
@Override
public void setLogWriter(PrintWriter arg0) throws SQLException {
}
@Override
public void setLoginTimeout(int arg0) throws SQLException {
}
@Override
public boolean isWrapperFor(Class<?> arg0) throws SQLException {
return false;
}
@Override
public <T> T unwrap(Class<T> arg0) throws SQLException {
return null;
}
}
注意: 上面的代码会报错 ,但是不是为了去实现它 而是学它的原理
嫌代码多的可 使用适配器模式创建 。
至于为什么报错 以后会了再说,现在主要是懂思想即可,后面直接用第三方的连接池.