Sep. 20 19:15~20:47
有一陣子沒寫技術性的文章,今天介紹《Implementation Patterns》書中的Pluggable Selector這個模式。有幾個還算常見的pattern名字前頭都帶有「Pluggable」這個字,例如Pluggable Adapter、Pluggable Behavior、Pluggable Block以及今天的主角Pluggable Selector。簡單的說,這些pattern名字中的「Pluggable」指的是可以藉由傳入參數或是設定某個物件的屬性(attribute or data member),來產生實體特有行為(instance-specific behavior)。
在傳統的物件導向設計中,產生實體特有行為最簡單也是最直接的方式就是透過繼承,讓子類別覆寫父類別的函數(function or method)以產生子類別特有的行為。但是如果每一個子類別只需要覆寫父類別的1~2個函數,採用這種方式將會產生很多只有一點點差異的子類別。
書中舉了JUnit的例子,為了讓JUnit可以自動執行測試案例,採用傳統的設計方法,子類別需要覆寫父類的runTest(),在裡面撰寫自己的測試案例。每一個代表測試案例(TestCase)的子類別只能有一個測試案例,顯然不是很好的設計方法(因為隨著測試案例增加,會產生非常、非常多的TestCase子類別)。
▼書中提到,如果把程式改成這樣,就可以把多個測試方法(test method)寫在同一個TestCase子類別裡面,只要改變name變數,就可以透過reflection技巧讓runTest()分別執行同一個類別裡面的多個測試方法。
1: String name;
2: public void runTest() thorws Exception {
3: Class [] noArguments = new Class[0];
4: Method method = getClass().getMethod(Name, noArguments);
5: method.invoke(this, new Object[0]);
6: }
***
透過reflection固然讓程式的行為變的比較動態,但付出的代價就是失去編譯期間的靜態檢查功能。有時候你發現類別的某些函數並沒有人呼叫它,於是把他們刪除。但程式執行之後卻出現錯誤,因為這些「看起來沒人呼叫」的函數,透過reflection的方式被其他物件使用。
不過這應該不算是什麼大問題,因為有了annotation之後,可以幫函數用annotation加上註記以提醒開發人員。加上如果開發人員有勤寫測試,可以大幅減少類似問題發生的機率。
但是,Pluggable Selector也不能爛用,否則寫出來的程式沒人看得懂,反倒是得不償失。
***
友藏內心獨白:軟硬體都可以Pluggable。
沒有留言:
張貼留言