通過連線池操作 理解裝飾者設計模式 自我理解
自我理解:裝飾者設計模式的方法增強,就是自定義一個類去實現我們需要增強的方法的介面,並定義一個成員變數物件去儲存我們之前的物件,
那麼這個成員變數所有呼叫的方法就是我們原來介面中的方法,因為成員變數物件 是我們原來物件的副本,然後改寫我們要增強的方法即可。
應用:
當我們建立資料庫連線池中連線時, 當我們用完我們建立的連線需要將連線放回到連線池(此處用集合模擬連線池)時,
此時Connection類中的close方法不能夠滿足我們的需求, 因為他是關閉連線,不是放回到連線池,
所以我們就想增強一下他的close方法,將這個方法重寫為當在連線池中呼叫close方法關閉連線時,我們將這個連線放回到連線池,
此時我們就用到了裝飾者設計模式。
自我理解:如果需要在增強後,真正的關閉連線 那麼我們需要自定義方法去獲取我們增強版的類的成員變數物件,因為這個物件就是原來的物件,再用他去呼叫我們增強類實現的接口裡面的方法,就可達到目的(其實就是將原來物件用副本物件代替執行原有的方法)
實際程式碼:
Connection conn = DriverManager...
MyConnection myConn = new MyConnection(conn);
myConn.close();//此方法增強了
myConn.commit();//底層呼叫C類具體方法,conn.commit()
連線池中之後使用都是MyConnection , pool.add(myConn)
步驟:
1.必須實現介面A
2.提供有參構造,引數型別為介面A
3.提供成員變數,存放構造方法介面實際引數(其他實現類)
4.實現需要增強的方法
5.實現不需要增強的方法,呼叫成員變數對應的方法即可
/** 目的:使用裝飾者設計模式,對Connection介面的close方法進行增強。
* 裝飾者設計模式固定的步驟:
* 介面A,自定義實現B,其他實現類C
* * 模式
* A a = C (工具類)
* B b = new B(a);
* * 實際程式碼
* Connection conn = DriverManager....
* MyConnection myConn = new MyConnection( conn );
* myConn.close(); //此方法增強了
* myConn.commit() ; //底層呼叫C類具體方法,conn.commit();
* **連線池中之後使用都是MyConnection ,pool.add(myConn);
*
* 1.必須實現介面A
* 2.提供有參構造,引數型別為介面A
* 3.提供成員變數,存放構造方法介面實際引數(其他實現類)
* 4.實現需要增強的方法
* 5.實現不需要增強的方法,呼叫成員變數對應的方法即可。
*
*/
public class MyConnection2 implements Connection {
private Connection conn;
private List<Connection> pool;
// public MyConnection2(Connection conn){
// this.conn = conn;
// }
public MyConnection2(Connection conn,List<Connection> pool){
this.conn = conn;
this.pool = pool;
}
//增強的方法--將當前連線歸還給連線池
@Override
public void close() throws SQLException {
//this 當前物件,表示當前連線
pool.add(this);
}
//可以真實關閉
public Connection getConnection(){
return this.conn;
}
// 不增強的方法
@Override
public void commit() throws SQLException {
this.conn.commit();
}
@Override
public void rollback(Savepoint savepoint) throws SQLException {
this.conn.rollback(savepoint);
}
具體實現 包括真實關閉
/** 進行方法增強,對close方法進行增強。
* 1.繼承,子類複寫父類的方法。必須明確父類(可以獲得父類名稱)。
* 通過工具類DriverManager獲得連線,無法確定父類。
* 2.設計模式--裝飾者,必須有介面【】
* 設計模式:就是一段固定的程式碼,為了解決固定的問題。
* 裝飾者目的:增強方法
* 3.動態代理,必須有介面
* 4.位元組碼增強,增強指定類,不需要介面
*
*/
public class MyPool4 {
//1 容器 -- LinkedList --> 增刪多,比較快
private static LinkedList<Connection> pool = new LinkedList<Connection>();
static{
//1.1 初始化連線池,提供3個連線
try {
//1) 註冊驅動
Class.forName("com.mysql.jdbc.Driver");
for(int i = 0 ; i < 3 ; i ++){
//2) 獲得連線
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/ee30_day10", "root", "1234");
// 將連線新增到池中
//pool.add(conn); //conn 提供連線的close存在缺陷,沒有將連線歸還給連線池
//3)將已經增強close的MyConnection新增到連線池中
MyConnection myConn = new MyConnection( conn , pool );
pool.add(myConn);
}
//3) JVM 虛擬機器關閉時,真實關閉連線
Runtime.getRuntime().addShutdownHook(new Thread(){
@Override
public void run() {
try {
Thread.sleep(100);
for(Connection myConn : pool){
if(myConn instanceof MyConnection){ //判斷前面變數是否是後面指定型別
MyConnection my = (MyConnection) myConn;
System.out.println("真實關閉" + my);
my.getConnection().close();
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//2 獲得連線,先判斷池中是否有,如果有移除。否則等待100毫秒,遞迴
public static Connection getConnection(){
//有
if(! pool.isEmpty()){
return pool.removeFirst();
}
//沒有
try {
Thread.sleep(100);
} catch (Exception e) {
}
return getConnection();
}
//3 釋放資源--將連線歸還給連線池(新增到池中)
public static void closeResource(Connection conn){
//conn.close(); //真的關閉連線
pool.add(conn);
}
}