scud(飛雲小俠) 2005-7-23 http://www.jscud.com 轉載請註明作者
【空接口的使用】
在接口使用的時候,空接口有2種情況:
1.類似Cloneable,Serializable,他們往往是做一個標記,表示需要某個功能.當然你也可以這麼用,來表示你的類具有某個功能,實現了你的某個接口.
2.你的接口繼承了別的接口(非空),你的接口本身沒有聲明函數.這種情況一般是你不希望用戶使用父接口來作爲參數類型,因爲他們的用途可能不同,此時就可以用空接口來實現.
第一種情況我們不再多說,搜索一下關於Cloneable,Serializable的文章就會了解很多.
我們來看下面的代碼:
public interface Text { String getText(); } public interface SqlText extends Text { } |
可以看到,Text接口是用於返回一個字符串.而SqlText是一個空接口,它繼承了Text接口.也就是說SqlText也是一種Text.但是我們可以知道,任何一個字符串不一定是Sql字符串,所以此時聲明瞭一個SqlText接口來用於表名當前的字符串是一個Sql字符串.你的函數可以這樣聲明:
public void doQuery(SqlText aSqlText)
而不是這樣
public void doQuery(Text aText)
避免用戶產生歧義的想法,一眼看去,就明白應該傳入一個Sql字符串.
【繼承層次過多】
一般來說,繼承的層次不要過多,否則使用者可能會討厭,找一個函數會很麻煩.很多Java語言檢查工具都建議你的繼承層次不要超過3層.
【Has A ,Is A,不要濫用繼承】
"我是一個Mp3","我有一個Mp3",其實很容易分辨.但是在實際應用中,往往存在把"我有一個Mp3"的情況當作"我是一個Mp3",或者是爲了偷懶方便而放鬆了對自己的要求,甚至還沾沾自喜,感覺找到一個捷徑.(scud以前也幹過這種事情).
以前我曾經這樣幹過:我的邏輯類直接繼承了我的數據庫訪問類,這樣我可以直接在邏輯類裏面訪問:
public MyLogic extends MyDBA aLogic.getInt("click"); aLogic.getString("name"); |
看起來是非常方便,但是你的邏輯類就牢牢綁在了DBA上,是一種非常不好的做法.現在我這樣聲明:
public MyLogic MyDBA adba; adba.getInt("click"); adba.getString("name"); |
其實代碼改動不大,但是你的邏輯類不在牢牢綁在DBA身上了,何樂而不爲.
其實這種現象在開發人員中間可能經常見到,我們要儘量避免.下面再來看一個例子:
//一個保存分頁信息的類
public class PageInfo { private int page; private int pageCount; private int recPerPage; private int recCount; //get,set method list... } |
一般的情況是,在Dao中進行分頁查詢,計算總記錄,總頁數等等,所以需要把PageInfo傳給Dao.而在邏輯類中,把傳回來的分頁信息數據推到FormBean或者是Action中.
也許你會這麼想,如果我的Action或者FormBean繼承了PageInfo,豈不是要省很多事.
千萬別這麼幹.並不是所有的動作都需要分頁信息,你的FormBean和PageInfo沒有繼承的關係.也就是說FormBean Has A PageInfo,但是不是Is A PageInfo.
【保持外觀/行爲一致】
外觀一致其實很容易理解,例如你用size()表示得到一個List的大小,那麼在所有的List類中你都用size()得到它的大小,這就是外觀一致.
外觀一致讓用戶更方便使用你的函數庫,不用記住幾個不同的表示同一個功能的函數名字.或者幾個名字相同功能卻不同的函數.那就很糟糕了.
行爲一致相對外觀一致就相對比較難做到,但是優秀的設計師肯定會讓他的成果行爲一致,而不是出人意料的行爲,也不是一套強行規定的行爲.
我們來看下面的代碼:
import java.util.HashMap; import java.util.Map;
class UserInfo |
可以看到,上面的代碼運行結果是"王小二",也就是說兒童團團長是王小二,王小二本身也是王小二,這一切正常.
現在我們把setUserInfo裏面的第一句註釋掉:
public void setUserInfo(String sName,UserInfo aInfo) { //userInfoMap.put(sName,aInfo); userInfoMap.put(aInfo.getName(),aInfo); } |
再次運行上面的代碼,我們發現兒童團團長不存在了,但是王小二還在.還可以看出,如果找"三班班長"的話,肯定也找不到,也就是說只有依據王小二的真名才能找到王小二,其他方法就不行了.
從上面的setUserInfo和getUserInfo分析,如果採用修改後的代碼,我們的程序就出現了行爲表現不一致,而這是令人迷惑不解的,我們set了半天,卻找不到,豈不是令人惱火!
當然上面的代碼比較簡單,通過簡單的修改就能做到行爲一致,但在實際編程中,往往因爲複雜的行爲操作,經常會造成行爲不一致,從而給開發人員帶來困惑.