相關讀書筆記列表
NO.18 優先考慮靜態成員類
嵌套類只為它的外圍類提供服務。
嵌套類分為四種:靜態成員類、非靜態成員類、匿名類和局部類(後面三種稱為內部類)
如果一個嵌套類的執行個體可以在它外類類的執行個體之外獨立存在,則這個嵌套類應該設定成靜態成員類(即:如果你聲明的成員類不要訪問外圍執行個體,那麼應該把static修飾符放到成員類的聲明中)。
匿名類的用法:
①建立一個函數對象;
②建立過程對象;
③在靜態Factory 方法的內部使用;
④在複雜的型別安全枚舉類型(它要求為每個執行個體提供單獨的子類)中,用於公有的靜態final域的初始化器中;
總結:四種不同的嵌套類都有自己不同的用途,如果一個嵌套類需要在單個方法之外任然是可見的,或者它太長,不適合放在一個方法內部,那麼應該使用成員類,如果成員類的每個執行個體都需要一個指向其外圍執行個體的引用,則把成員類做成非靜態;否則就做成靜態,假設一個嵌套類屬於一個方法的內部,如果你只需要在一個地方建立它的執行個體,並且已經有了一個預先存在的類型可以說明這個類的特徵,則把它做成匿名類;否則就做成局部類。
註:以下幾點(NO.19 ~ NO.22)是講解關於C語言結構的替代方案,由於本人只從事java的開發,所以跳過此章節,為了保證筆記的完整性,從其他地方轉載NO.19 ~ NO.22的筆記。
NO.19 用類代替結構
JAVA剛面世的時候,很多C程式員都認為用類來代替結構現在太複雜,代價太大了,但是實際上,如果一個JAVA的類退化到只包含一個資料域的話,這樣的類與C語言的結構大致是等價的。
比方說下面兩個程式片段:
class Point<br /> {<br /> private float x;<br /> private float y;<br /> }
實際上這段代碼和C語言的結構基本上沒什麼區別,但是這段代碼恐怕是眾多OO設計Fans所不齒的,因為它沒有體現封裝的優異性,沒有體現物件導向設計的優點,當一個域被修改的時候,你不可能再採取任何輔助的措施了,那我們再來看一看採用包含私人域和共有存取方法的OO設計程式碼片段:
class Point<br /> {<br /> private float x;<br /> private float y;<br /> public Point(float x,float y)<br /> {<br /> this.x=x;<br /> this.y=y;<br /> }<br /> public float getX(){retrun x;}<br /> public float getY(){return y;}<br /> public void setX(float x){this.x=x;}<br /> public void setY(float y){this.y=y;}<br /> }
單從表面上看,這段代碼比上面那個多了很多行,還多了很多函數,但是仔細想一下,這樣的OO設計,似乎更人性化,我們可以方面的對範圍進行提取,修改等操作,而不直接和範圍發生關係,這樣的代碼不僅讓人容易讀懂,而且很安全,還吸取了物件導向程式設計的靈活性,試想一下,如果一個共有類暴露它的範圍,那麼想要在將來的版本中進行修改是impossible的,因為共有類的客戶代碼已經遍布各處了。
需要提醒一點的是,如果一個類是包級私人的,或者是一個私人的嵌套類,則直接暴露其範圍並無不妥之處。
NO.20 用類層次來代替聯合
我們在用C語言來進行開發的時候,經常會用到聯合這個概念,比如:
typedef struct{<br /> double length;<br /> double width;<br />}rectangleDimensions_t;
那我們在JAVA裡面沒有聯合這個概念,那我們用什麼呢?對!用繼承,這也是JAVA最吸引我的地方之一,它可以使用更好的機制來定義耽擱資料類型,在 Bruce Eckel的Thinking in java裡面也多次提到了一個和形狀有關的例子,我們可以先籠統的定義一個抽象類別,即我們通常所指的超類,每個操作定義一個抽象的方法,其行為取決於標籤的值,如果還有其他的操作不依賴於標籤的值,則把操作變成根類(繼承的類)中的具體方法。
這樣做的最重要的優點是:類層次提供了類型的安全性。
其次代碼非常明了,這也是OO設計的優點。
而且它很容易擴充,即使是面向多個方面的工作,能夠同樣勝任。
最後它可以反映這些類型之間本質上的層次關係,從而允許更強的靈活性,以便編譯時間類型檢查。
NO.21 用類來代替enum結構
Java程式設計語言提出了型別安全枚舉的模式來替代enum結構,它的基本思想很簡單:定義一個類來代表枚舉類型的單個元素,並且不提供任何公有的建構函式,相反,提供公有靜態final類,使枚舉類型中的每一個常量都對應一個域。
型別安全枚舉類型的一個缺點是,裝載枚舉類的和構造常量對象時,需要一定的時間和空間開銷,除非是在資源很受限制的裝置比如蜂窩電哈和烤麵包機上,否則在實際中這個問題不會被考慮。
總之,型別安全枚舉類型明顯優於int類型,除非實在一個枚舉類型主要被用做一個集合元素,或者主要用在一個資源非常不受限的環境下,否則型別安全枚舉類型的缺點都不成問題,依次,在要求使用一個枚舉類型的環境下,我們首先應考慮型別安全枚舉類型模式。
NO.22 用類和介面來代替函數指標
眾所周知,JAVA語言和C的最大區別在於,前者去掉了指標,小生第一次接觸JAVA的時候覺得好不習慣,因為突然一下子沒了指標,覺得好不方面啊,C語言的精髓在於其指標的運用,而JAVA卻把它砍掉了,讓人好生鬱悶,不過隨著時間的推移,我漸漸明白了用類和介面的應用也同樣可以提供同樣的功能,我們可以直接定義一個這樣一個類,他的方法是執行其他方法上的操作,如果一個類僅僅是匯出這樣一個方法,那麼它實際上就是一個指向該方法的指標,舉個例子:
class StringLengthComprator{<br />public int compare(String s1,String s2)<br />{<br />return s1.length()-s2.length();<br />}<br />}
這個類匯出一個帶兩個字串的方法,它是一個用於字串比較的具體策略。它是無狀態的,沒有域,所以,這個類的所有執行個體在功能上都是等價的,可以節省不必要的對象建立開銷。但是我們不好直接把這個類傳遞給可戶使用,因為可戶無法傳遞任何其他的比較策略。相反,我們可以定義一個介面,即我們在設計具體策略類的時候還需要定義一個策略介面:
public interface Comparator{<br /> public int compare(Object o1,Object o2);<br />}
我們完全可以依照自己的需要來定義它。
具體的策略類往往使用匿名類聲明。
在JAVA中,我們為了實現指標的模式,聲明一個介面來表示該策略,並且為每個具體策略聲明一個實現了該介面的類,如果一個具體策略只被使用一次的話,那麼通常使用匿名類來聲明和執行個體化這個具體策略類,如果一個策略類反覆使用,那麼它的類通常是一個私人的的靜態成員類。