潛魚(yú)在淵

          Concentrating on Architectures.

          posts - 77, comments - 309, trackbacks - 0, articles - 0
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          代碼檢查(2)

          Posted on 2008-10-25 13:55 非魚(yú) 閱讀(2386) 評(píng)論(6)  編輯  收藏 所屬分類(lèi): 面向?qū)ο笤O(shè)計(jì)Java技術(shù)
          2. instanceof檢查鏈

          這個(gè)問(wèn)題是連續(xù)使用if ... else + instanceof檢查來(lái)判斷一個(gè)對(duì)象的類(lèi)型,并采取不同的處理邏輯。示例代碼如下:

          public void method(Fruit fruit) {
            if (fruit instanceof Apple) {
              ...
            }
            else if (fruit instanceof Orange) {
              ...
            }
            else if .....
          }

          這不是面向?qū)ο蟮姆椒ǎ耆珱](méi)有利用到多態(tài)的面向?qū)ο筇匦?。我相信一個(gè)合格的程序員是不會(huì)寫(xiě)出這樣的編碼的,這一般是新手程序員,特別是對(duì)面向?qū)ο罄斫獠簧羁痰某绦騿T會(huì)犯的毛病。改正的方法就是在Fruit類(lèi)中增加一個(gè)方法,并在Apple、Orange等子類(lèi)中實(shí)現(xiàn)此方法:

          public abstract class Fruit {
            public int m();
          }

          當(dāng)然,在環(huán)境允許的情況下,盡可能使用protected而不是public來(lái)定義這個(gè)方法。

          現(xiàn)在我們來(lái)看一個(gè)復(fù)雜一點(diǎn)的,同樣還是instanceof檢查的問(wèn)題,但這個(gè)檢查只涉及了Fruit諸多子類(lèi)中的一部分,而其他的子類(lèi),行為是一致的。這時(shí)候我們需要在Fruit中引入一致行為的實(shí)現(xiàn):

          public abstract class Fruit {
            public int m() {
              //一般的實(shí)現(xiàn)。
              ...
            }
          }

          而更加復(fù)雜的行為需要對(duì)應(yīng)復(fù)雜的設(shè)計(jì),通過(guò)對(duì)具體水果的抽象,可以發(fā)現(xiàn)這些水果可以抽象為幾個(gè)較為一般的類(lèi):

          public abstract class Fruit {
            public int m(){
              ...
            }
          }

          public class TypeAFruit extends Fruit {
            public int m(){
              //特定類(lèi)型的實(shí)現(xiàn)。
            }
          }

          public class TypeBFruit extends Fruit {
            public int m(){
              // 特定類(lèi)型的實(shí)現(xiàn)。
            }
          }

          ...

          關(guān)于類(lèi)的繼承層次的問(wèn)題,有一種說(shuō)法是“原則上”控制在一定的數(shù)量之內(nèi)。一般來(lái)說(shuō) 這個(gè)說(shuō)法是有道理的(特別是對(duì)初學(xué)者,它可以有效的避免“濫繼承”),但不是放之四海皆準(zhǔn)的道理,不要把它教條化。

          說(shuō)到繼承層次,不得不提到抽象層次。我們總是在一定的抽象層次上解決問(wèn)題,抽象層次決定了你解決問(wèn)題的實(shí)現(xiàn)的復(fù)雜程度。設(shè)計(jì)以簡(jiǎn)潔為美,不要把設(shè)計(jì)復(fù)雜化。但簡(jiǎn)潔并不意味著“少”,簡(jiǎn)潔的真正涵義是:模型不比模型所表達(dá)的事物更加復(fù)雜,不要把“本來(lái)簡(jiǎn)單”的東西復(fù)雜化,也不要把本來(lái)復(fù)雜的東西簡(jiǎn)單化。

          我所要表達(dá)的是,設(shè)計(jì)應(yīng)該是簡(jiǎn)潔的,但不是“簡(jiǎn)單”的。“設(shè)計(jì)應(yīng)該簡(jiǎn)單”的說(shuō)法,是來(lái)自翻譯的問(wèn)題,還是來(lái)自理解的問(wèn)題?簡(jiǎn)單會(huì)導(dǎo)向“偷工減料”,而簡(jiǎn)潔則要求不要在設(shè)計(jì)中加料(特別是廢料)。

          一個(gè)繼承結(jié)構(gòu)有多少層才是合適的?最上層的類(lèi)或接口對(duì)應(yīng)著“一般概念”,最下層的類(lèi)一定可以實(shí)例化為具體的對(duì)象,這中間有多少“層”,就有多少抽象層次。決定抽象層次,也就是決定你的繼承層次的原則有二:

          • 客戶(hù)代碼的需要:客戶(hù)代碼是指調(diào)用你的類(lèi)繼承層次中的某些類(lèi)的代碼,客戶(hù)代碼需要知道某個(gè)層次的細(xì)節(jié)。此外需要注意的是,客戶(hù)代碼應(yīng)該盡量使用最上層的“一般概念”。
          • 重用的需要:在具體的不同類(lèi)中存在相同代碼的時(shí)候,就要考慮有沒(méi)有可能進(jìn)行抽象,形成一個(gè)用于重用目的的父類(lèi)。
          類(lèi)繼承層次的設(shè)計(jì)也不是一成不變的,按照上面這兩個(gè)原則,當(dāng)客戶(hù)代碼不再需要某個(gè)層次時(shí),或者當(dāng)重用代碼不可能(一般標(biāo)志就是大量的override)時(shí),就要考慮改變繼承體系的設(shè)計(jì)。


          汗,感覺(jué)后面有點(diǎn)越扯越遠(yuǎn)了。。。


          , ,


          評(píng)論

          # re: 編碼問(wèn)題(2)  回復(fù)  更多評(píng)論   

          2008-10-25 18:07 by eng?
          為什么java程序難以維護(hù),就是你們這些所謂的“合格程序員”寫(xiě)的程序

          # re: 編碼問(wèn)題(2)[未登錄](méi)  回復(fù)  更多評(píng)論   

          2008-10-25 22:54 by Matthew
          樓上寫(xiě)的不知啥意思,樓主講得很好啊,要可擴(kuò)展又能應(yīng)對(duì)實(shí)際項(xiàng)目的需要。

          # re: 編碼問(wèn)題(2)  回復(fù)  更多評(píng)論   

          2008-10-26 00:39 by 非魚(yú)
          @Matthew
          兄弟沒(méi)有看懂樓上的話(huà)?我非常同意他的結(jié)論,我和比我在先的大量程序員們,不知道以前寫(xiě)出了多少爛程序,一路踩著大量的項(xiàng)目的尸體,才能變得聰明一點(diǎn)。但合格的程序員有不少,其中又有多少人是合格的老師或者說(shuō)引導(dǎo)者呢?于是雖然從事這個(gè)職業(yè)的人越來(lái)越多,寫(xiě)出來(lái)的代碼質(zhì)量卻未見(jiàn)提高。能夠給你帶來(lái)益處我當(dāng)然高興;我卻仍然為自己知道的遲而感到遺憾。使后來(lái)者感到無(wú)助是我們這些先行者的錯(cuò),他們可能會(huì)因此而走向極端,而我們要做的,不是把他們劃到圈子之外。

          # re: 編碼問(wèn)題(2)  回復(fù)  更多評(píng)論   

          2008-10-26 12:49 by 隔葉黃鶯
          能把本來(lái)復(fù)雜的東西簡(jiǎn)單化

          若不失完整的表達(dá)了需求何樂(lè)而不為

          # re: 編碼問(wèn)題(2)  回復(fù)  更多評(píng)論   

          2008-10-27 23:28 by 非魚(yú)
          @隔葉黃鶯
          能把本來(lái)復(fù)雜的東西簡(jiǎn)單化,就是舍棄一些不重要的細(xì)節(jié),實(shí)際就是“抽象”了。如果抽象可以滿(mǎn)足需求自然可以;否則必然要求在較低的抽象層次上建模。

          # re: 編碼問(wèn)題(2)  回復(fù)  更多評(píng)論   

          2008-10-28 17:15 by flybean
          頂樓的說(shuō)法有些欠妥。不僅僅是JAVA代碼難維護(hù)的問(wèn)題。

          非魚(yú)所舉的例子,如果能來(lái)源于實(shí)際項(xiàng)目,效果會(huì)好一些。畢竟水果的這個(gè)例子不痛不癢。
          主站蜘蛛池模板: 丰顺县| 灵寿县| 沾化县| 梁平县| 盱眙县| 桂平市| 霸州市| 平潭县| 和政县| 莎车县| 呈贡县| 织金县| 怀仁县| 博兴县| 宿州市| 威宁| 温宿县| 轮台县| 张家界市| 南川市| 旌德县| 遵化市| 临桂县| 石台县| 策勒县| 来安县| 蓬安县| 高清| 崇阳县| 墨脱县| 龙井市| 武定县| 沁源县| 沾化县| 尼木县| 米林县| 鲁甸县| 乐亭县| 怀安县| 张家川| 井陉县|