作者:夏彥端

看了mingjava在網(wǎng)站上的前三篇文章,覺得這本書確實值得大家認真的讀,后來跟mingjava說想接著他的寫,于是就有了這接下來的文章,希望不是狗尾續(xù)貂,寫得不好,大家多多給我提意見,我會努力去改進的。

     由于以前學過C語言,所以對C還是蠻有感情,而JAVA和C又有很多相似之處,很多從C轉(zhuǎn)過來學習JAVA的兄弟,可能一開始都不是很適應,因為很多在C里面的結(jié)構(gòu)在JAVA里面都不能使用了,所以下面我們來介紹一下C語言結(jié)構(gòu)的替代。

      Item 19:用類代替結(jié)構(gòu)

      JAVA剛面世的時候,很多C程序員都認為用類來代替結(jié)構(gòu)現(xiàn)在太復雜,代價太大了,但是實際上,如果一個JAVA的類退化到只包含一個數(shù)據(jù)域的話,這樣的類與C語言的結(jié)構(gòu)大致是等價的。

      比方說下面兩個程序片段:

      class Point

      {

       private float x;

       private float y;

      }

      實際上這段代碼和C語言的結(jié)構(gòu)基本上沒什么區(qū)別,但是這段代碼恐怕是眾多OO設(shè)計Fans所不齒的,因為它沒有體現(xiàn)封裝的優(yōu)異性,沒有體現(xiàn)面向?qū)ο笤O(shè)計的優(yōu)點,當一個域被修改的時候,你不可能再采取任何輔助的措施了,那我們再來看一看采用包含私有域和共有訪問方法的OO設(shè)計代碼段:

      class Point

      {
       private float x;
       private float y;
       public Point(float x,float y)
       {
             this.x=x;
             this.y=y;
       }
        public float getX(){retrun x;}

        public float getY(){return y;}

        public void setX(float x){this.x=x;}

        public void setY(float y){this.y=y;}

      }

        單從表面上看,這段代碼比上面那個多了很多行,還多了很多函數(shù),但是仔細想一下,這樣的OO設(shè)計,似乎更人性化,我們可以方面的對值域進行提取,修改等操作,而不直接和值域發(fā)生關(guān)系,這樣的代碼不僅讓人容易讀懂,而且很安全,還吸取了面向?qū)ο蟪绦蛟O(shè)計的靈活性,試想一下,如果一個共有類暴露它的值域,那么想要在將來的版本中進行修改是impossible的,因為共有類的客戶代碼已經(jīng)遍布各處了。

需要提醒一點的是,如果一個類是包級私有的,或者是一個私有的嵌套類,則直接暴露其值域并無不妥之處。

 

Item 20:用類層次來代替聯(lián)合

我們在用C語言來進行開發(fā)的時候,經(jīng)常會用到聯(lián)合這個概念,比如:

       typedef struct{

     double length;

     double width;    

}rectangleDimensions_t;

那我們在JAVA里面沒有聯(lián)合這個概念,那我們用什么呢?對!用繼承,這也是JAVA最吸引我的地方之一,它可以使用更好的機制來定義耽擱數(shù)據(jù)類型,在Bruce Eckel的Thinking in java里面也多次提到了一個和形狀有關(guān)的例子,我們可以先籠統(tǒng)的定義一個抽象類,即我們通常所指的超類,每個操作定義一個抽象的方法,其行為取決于標簽的值,如果還有其他的操作不依賴于標簽的值,則把操作變成根類(繼承的類)中的具體方法。

這樣做的最重要的優(yōu)點是:類層次提供了類型的安全性。

其次代碼非常明了,這也是OO設(shè)計的優(yōu)點。

而且它很容易擴展,即使是面向多個方面的工作,能夠同樣勝任。

最后它可以反映這些類型之間本質(zhì)上的層次關(guān)系,從而允許更強的靈活性,以便編譯時類型檢查。
 

Item 21:用類來代替enum結(jié)構(gòu)

Java程序設(shè)計語言提出了類型安全枚舉的模式來替代enum結(jié)構(gòu),它的基本思想很簡單:定義一個類來代表枚舉類型的單個元素,并且不提供任何公有的構(gòu)造函數(shù),相反,提供公有靜態(tài)final類,使枚舉類型中的每一個常量都對應一個域。

類型安全枚舉類型的一個缺點是,裝載枚舉類的和構(gòu)造常量對象時,需要一定的時間和空間開銷,除非是在資源很受限制的設(shè)備比如蜂窩電哈和烤面包機上,否則在實際中這個問題不會被考慮。

 總之,類型安全枚舉類型明顯優(yōu)于int類型,除非實在一個枚舉類型主要被用做一個集合元素,或者主要用在一個資源非常不受限的環(huán)境下,否則類型安全枚舉類型的缺點都不成問題,依次,在要求使用一個枚舉類型的環(huán)境下,我們首先應考慮類型安全枚舉類型模式。

 

Item 22:用類和接口來代替函數(shù)指針

眾所周知,JAVA語言和C的最大區(qū)別在于,前者去掉了指針,小生第一次接觸JAVA的時候覺得好不習慣,因為突然一下子沒了指針,覺得好不方面啊,C語言的精髓在于其指針的運用,而JAVA卻把它砍掉了,讓人好生郁悶,不過隨著時間的推移,我漸漸明白了用類和接口的應用也同樣可以提供同樣的功能,我們可以直接定義一個這樣一個類,他的方法是執(zhí)行其他方法上的操作,如果一個類僅僅是導出這樣一個方法,那么它實際上就是一個指向該方法的指針,舉個例子:

 class StringLengthComprator{

public int compare(String s1,String s2)

{

return s1.length()-s2.length();

}

}

這個類導出一個帶兩個字符串的方法,它是一個用于字符串比較的具體策略。它是無狀態(tài)的,沒有域,所以,這個類的所有實例在功能上都是等價的,可以節(jié)省不必要的對象創(chuàng)建開銷。但是我們不好直接把這個類傳遞給可戶使用,因為可戶無法傳遞任何其他的比較策略。相反,我們可以定義一個接口,即我們在設(shè)計具體策略類的時候還需要定義一個策略接口:

      public interface Comparator{

           public int compare(Object o1,Object o2);

}

  我們完全可以依照自己的需要來定義它。

具體的策略類往往使用匿名類聲明。

在JAVA中,我們?yōu)榱藢崿F(xiàn)指針的模式,聲明一個接口來表示該策略,并且為每個具體策略聲明一個實現(xiàn)了該接口的類,如果一個具體策略只被使用一次的話,那么通常使用匿名類來聲明和實例化這個具體策略類,如果一個策略類反復使用,那么它的類通常是一個私有的的靜態(tài)成員類。