装饰者设计模式
如果想要对某个对象的功能进行扩展时,就可以使用装饰者设计模式。
装饰者设计模式的使用方式:
- 编写一个类,实现与被包装类相同的接口。【就是说和你新建的装饰类要模仿别的一样 这里指的是 实现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; } }
注意: 上面的代码会报错 ,但是不是为了去实现它 而是学它的原理
嫌代码多的可 使用适配器模式创建 。
至于为什么报错 以后会了再说,现在主要是懂思想即可,后面直接用第三方的连接池.