JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » Software Design » Design Pattern  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to topicthreaded modego to previous topicgo to next topic
本主題所含的標籤
無標籤
作者 一個複雜繼承關係的Decorator模式
legendker





發文: 41
積分: 0
於 2014-03-21 16:25 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
最近在研究開發一個幫助類程式

主要的目的是針對PreparedStatement和CallableStatement做一個Log的紀錄 (因為原始的SQL會包含很多問號)

我的實作方式是使用Decorator模式
程式大概如下

Abstract Decorator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public abstract class PreparedStatementDecorator implements PreparedStatement {
 
  protected PreparedStatement delegate;
  protected String sql;
 
  protected final Object guardian = new Object() {
    protected void finalize() {
      try {
        super.finalize();
        destroy();
      } catch (Throwable e) {
        e.printStackTrace();
      }
    }
        };
 
  public PreparedStatementDecorator(PreparedStatement statement, String sql) {
    if (statement == null)
      throw new NullPointerException("Statement is empty : " + sql);
    this.delegate = statement;
    this.sql = sql;
    init();
  }
  
  protected abstract void init();
  
  protected abstract void destroy() throws SQLException;
 
  public void addBatch() throws SQLException {
    delegate.addBatch();
  }
 
  public void setRef(int i, Ref x) throws SQLException {
    delegate.setRef(i, x);
  }
 
  public void setShort(int parameterIndex, short x) throws SQLException {
    delegate.setShort(parameterIndex, x);
  }
         
... 以下還有一堆Method,同樣用委派的方式
 
}


Adapter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class PreparedStatementDecoratorAdapter extends PreparedStatementDecorator {
 
  public PreparedStatementDecoratorAdapter(PreparedStatement statement, String sql) {
    super(statement, sql);
  }
 
  protected void init() {
    
  }
  
  protected void destroy() throws SQLException {
    close();
  }
  
  public void addBatch() throws SQLException {
    super.addBatch();
  }
 
  public void setRef(int i, Ref x) throws SQLException {
    super.setRef(i, x);
  }
 
  public void setShort(int parameterIndex, short x) throws SQLException {
    super.setShort(parameterIndex, x);
  }
 
        ... 同樣有一堆類似的Method
   


Concrete Decorator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class DebuggablePreparedStatement extends PreparedStatementDecoratorAdapter {
 
  private List variables;
  private boolean onDebug = false;
  private String filteredSQL;
  
  private SQLTranslator translator = new DefaultSQLTranslator();
  
  public DebuggablePreparedStatement(PreparedStatement statement, String sql) {
    super(statement, sql);
  }
  
  protected void init() {
    variables = new ArrayList(getPreparedColumnCount(sql));
  }
 
  public void setRef(int i, Ref x) throws SQLException {
    super.setRef(i, x);
    keepExpression(i, x);
       }
 
  public void setShort(int parameterIndex, Short x) throws SQLException {
    super.setRef(i, x);
    keepExpression(i, x);
  }
 
        public boolean execute() throws SQLException {
    if (onDebug)
      logSQL();
    return super.execute();
  }
  
  public boolean isDebugOn() {
    return onDebug;
  }
      
  private void keepExpression(int parameterIndex, InputStream x, int length) throws SQLException {
 
    if (!onDebug) 
      return;
    
              // ... 這裡會去紀錄setArgument的變數
  }
  
  public void logSQL() {
    // 這裡會去將儲存的變數取出變成完整的SQL Statement
  }
 


到這裡為止好像一切都還OK
不過問題來了,我還要針對CallableStatement做一樣的動作
而CallableStatement extends PreparedStatement
也許我可以同樣的方式再做一次,可是又不想多寫重複的一堆code

所以我讓抽象的裝飾者先繼承PreparedStatementDecoratorAdapter
再將CallableStatement多宣告的Method一一實作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
public abstract class CallableStatementDecorator extends PreparedStatementDecoratorAdapter implements CallableStatement {
 
  protected CallableStatement delegate;
  
  public CallableStatementDecorator(CallableStatement statement, String sql) {
    super(statement, sql);
  }
  
  public Array getArray(int i) throws SQLException {
    return delegate.getArray(i);
  }
 
  public Array getArray(String parameterName) throws SQLException {
    return delegate.getArray(parameterName);
  }
 
        ... 同樣有一堆Method


現在我要開始實作Concrete Decorator了
目的和上述的DebuggablePreparedStatement一樣
不過這時又發現,只要是interface PreparedStatement所宣告的方法,在實作上會是一模一樣的

這時回頭來看 才發現我的繼承層次多到恐怖,並且要達到同樣的目的大概只能靠多重繼承(但在Java這是不允許的,並且也不好)

請問各位高手,我還能怎麼調整我的程式架構呢?
謝謝啦!!


reply to postreply to post
作者 Re:一個複雜繼承關係的Decorator模式 [Re:legendker]
evabioz





發文: 8
積分: 0
於 2014-03-22 10:08 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
我是不太懂Design Patten...
既然Debuggable Callable屬於PreparedStatement延伸
在PreparedStatementDecorator類implement DebuggableStatement與CallableStatement
由Facotry協調 Blush


reply to postreply to post
作者 Re:一個複雜繼承關係的Decorator模式 [Re:legendker]
legendker





發文: 41
積分: 0
於 2014-04-09 12:07 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
謝謝幫忙!
我最後放棄使用Decorator
直接用flag去判斷是否啟用log的機制
好像單純許多


reply to postreply to post
作者 Re:一個複雜繼承關係的Decorator模式 [Re:legendker]
qrtt1





發文: 1746
積分: 31
於 2014-04-09 12:41 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
要 log sql 當然是由 jdbc driver 下手比較快啊。
這樣的 library 應該有人寫好了,例如 https://code.google.com/p/log4jdbc/
可以找幾套來比看看想用哪個

改變通常只是加新的 library 與 jdbc connection string 要改一下,
所以在 production vs development 切換很快。


reply to postreply to post
蝸牛角上爭何事?石火光中寄此身,隨富隨貧且歡樂,不開口笑是癡人。
my notes
作者 Re:一個複雜繼承關係的Decorator模式 [Re:legendker]
qrtt1





發文: 1746
積分: 31
於 2014-04-09 12:48 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
另外,產生大量的 delegation method 要用 IDE 幫忙比較快:
https://www.youtube.com/watch?v=l0cecpSHRkE

PS. 如果你不想要用 jdbc driver 的方法,真的想要自己實作,那用 AOP solution 也是一招。


reply to postreply to post
蝸牛角上爭何事?石火光中寄此身,隨富隨貧且歡樂,不開口笑是癡人。
my notes
» JWorld@TW »  Software Design » Design Pattern

reply to topicthreaded modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8