OO經(jīng)過(guò)這么多年的錘煉和考驗(yàn)證明是極好的,雖然也有些的人提出一些反面的意見(jiàn),證明時(shí)代在發(fā)展、進(jìn)步大家需要更先進(jìn)的設(shè)計(jì)方法,不過(guò)OO終歸是目前應(yīng)用最為廣泛也最為適用的程序設(shè)計(jì)方法學(xué)。個(gè)人覺(jué)得適用最為重要,畢竟OO是能夠很好解決大多數(shù)復(fù)雜系統(tǒng)設(shè)計(jì)的。不過(guò)同時(shí)OO也讓設(shè)計(jì)者陷入一個(gè)兩難的境地。一來(lái)容易設(shè)計(jì)過(guò)輕,也就是設(shè)計(jì)的不夠,發(fā)揮不了OO的強(qiáng)大和精妙之處,面向過(guò)程和面向?qū)ο蟮膴A雜反而使得實(shí)現(xiàn)者摸不著頭腦非常痛苦(很多時(shí)候這里指的設(shè)計(jì)者和實(shí)現(xiàn)著會(huì)是同一個(gè)人);二來(lái)容易設(shè)計(jì)過(guò)度,讓OO從一個(gè)手中的工具變成了一塊腳下的石頭,讓實(shí)現(xiàn)者工作起來(lái)異常的不順利,覺(jué)得做了很多脫了褲子放屁的事情(請(qǐng)容許我的粗魯,因?yàn)槲以僖舱也坏奖冗@個(gè)更好的比喻了)。
要解決這些問(wèn)題往往需要經(jīng)驗(yàn)的積累和技巧的總結(jié),知道OO理論的人不少,真正在設(shè)計(jì)中運(yùn)用的好的確實(shí)不多。當(dāng)然OO設(shè)計(jì)中最最重要的一個(gè)部分就是繼承了,下面列舉一些常見(jiàn)的繼承設(shè)計(jì)技巧,讀過(guò)《Core Java》的人可能對(duì)它們非常熟悉,我結(jié)合我自己的理解做一些說(shuō)明,也當(dāng)作一個(gè)學(xué)習(xí)。當(dāng)然不是記住了這些所謂的技巧就學(xué)會(huì)了繼承設(shè)計(jì),總的來(lái)講設(shè)計(jì)是需要遵循一定規(guī)律、結(jié)合實(shí)際情況、發(fā)揮自己的經(jīng)驗(yàn)而做出的,還是需要自己多多總結(jié)和積累。
1. 將公共操作和域放置在超類 顯然這是繼承最基本的目的,減少編碼量,減少業(yè)務(wù)關(guān)注面。讓子類更多關(guān)注自己的業(yè)務(wù)實(shí)現(xiàn),而公共的由共同的超類去操心。
2. 不要使用受保護(hù)的域 很多程序員其實(shí)都很喜歡“受保護(hù)的”(protected)這種作用域,特別是應(yīng)用在域上,因?yàn)樵谶@種作用域的作用下子類可以輕松的直接訪問(wèn)超類中相應(yīng)的域,可能也覺(jué)得這是理所當(dāng)然的事情,因?yàn)榧热辉谧宇愔欣^承了這個(gè)域而不能直接使用它還需要使用super關(guān)鍵字來(lái)調(diào)用超類方法去訪問(wèn)往往顯得很別扭和難看。但是protected機(jī)制會(huì)帶來(lái)很嚴(yán)重的安全問(wèn)題,第一,因?yàn)樽宇惣鲜菬o(wú)限制的,任何人都可以由一個(gè)類派生出另外一個(gè)子類,并編寫(xiě)代碼直接訪問(wèn)protected的實(shí)例域,從而破壞封裝性;第二,在Java中同一個(gè)包中的所有類都可以訪問(wèn)protected域,而不管它是否為這個(gè)類的子類。
所以推薦在盡可能的情況下把域設(shè)置為私有,不允許外部直接訪問(wèn)甚至修改。但其實(shí)很多初學(xué)者,包括一些編程老手都沒(méi)辦法理解和接受這種做法。我個(gè)人認(rèn)為如果OO失去了封裝性就好比失去了靈魂的空殼,沒(méi)有了什么意義,反而變成累贅而已。
3. 使用繼承實(shí)現(xiàn)is-a關(guān)系 如果拋開(kāi)所謂的設(shè)計(jì)思想來(lái)看,實(shí)現(xiàn)繼承最基本的目的就是節(jié)省代碼量,并且很容易就做到。但這樣往往很多人會(huì)濫用繼承,純粹為了節(jié)約代碼而節(jié)約代碼,而沒(méi)有顧及超類與子類的關(guān)系導(dǎo)致在實(shí)現(xiàn)其他相關(guān)問(wèn)題的時(shí)候帶來(lái)很多麻煩,反而會(huì)多寫(xiě)很多代碼,撿了芝麻丟了西瓜。
繼承應(yīng)該要遵循is-a關(guān)系,要判斷是否遵循了is-a關(guān)系也有個(gè)很簡(jiǎn)單的辦法,就是你念出這么一句話:“子類”是個(gè)“超類”,看是否合理。例如有一個(gè)雇員(Employee)類繼承與人(Person),這個(gè)時(shí)候就有這樣的關(guān)系:雇員是個(gè)人,顯然是正確的。
4. 除非所有繼承的方法都有意義,否則不要繼承 當(dāng)子類和超類之間遵循了is-a關(guān)系,但子類從超類繼承來(lái)的某些方法對(duì)于子類是沒(méi)有意義的,甚至是實(shí)現(xiàn)錯(cuò)誤功能的,這個(gè)時(shí)候應(yīng)該取消繼承關(guān)系,因?yàn)檫@相當(dāng)?shù)奈kU(xiǎn)。或者可以選擇重新審視你的設(shè)計(jì)。
5. 在覆蓋方法的時(shí)候,不要改變預(yù)期的行為 結(jié)合上面4中的觀點(diǎn),有些人可能會(huì)說(shuō)這個(gè)很簡(jiǎn)單,把意義不同的方法在子類中重寫(xiě),或者干脆什么也不做,也或者拋出一個(gè)異常不久解決了,so easy!其實(shí)這樣也是違背OO思想的,應(yīng)該盡量保持覆蓋方法的預(yù)期行為,只可能因?yàn)楦髯缘臉I(yè)務(wù)含義而改變實(shí)現(xiàn)方式,但是語(yǔ)義和行為是要保證的,就好像超類有個(gè)方法名字叫add是用來(lái)做加法的,但是你一定要極端的在子類中重寫(xiě)了它,里面的代碼偷偷實(shí)現(xiàn)了一個(gè)減法,這種做法的危險(xiǎn)我想很容易理解。為什么說(shuō)是偷偷的,因?yàn)榭赡苤挥心阒肋@里是做了減法,或者說(shuō)幾個(gè)星期后你自己都認(rèn)為這個(gè)方法實(shí)現(xiàn)的是一個(gè)加法運(yùn)算!
6. 使用多態(tài),而非類型信息 很多時(shí)候需要判斷當(dāng)前對(duì)象的類型來(lái)執(zhí)行相應(yīng)不同的方法,看下面的示例代碼:
1 if(x is of type 1)
2 action1(x);
3 else if(x is of type 2)
4 action2(x);
這個(gè)時(shí)候應(yīng)該去考慮action1和action2是不是表示同一個(gè)概念,如果是就應(yīng)該使用多態(tài)性來(lái)處理。這個(gè)時(shí)候應(yīng)該定義一個(gè)方法放置在這兩個(gè)類的超類或者接口中,然后就可以調(diào)用
1 x.action();
讓語(yǔ)言提供的多態(tài)性自己去找應(yīng)該調(diào)用那個(gè)類的方法來(lái)實(shí)現(xiàn)。是不是像極了某種模式:)
7. 不要過(guò)多的使用反射 個(gè)人覺(jué)得Java擁有了反射機(jī)制簡(jiǎn)直就是太強(qiáng)大了,在運(yùn)行時(shí)能夠查看甚至修改、調(diào)用域和方法極大的提高了程序?qū)崿F(xiàn)的靈活性和技巧性。以至于我甚至有一段時(shí)間把Java當(dāng)作JavaScript來(lái)玩(愛(ài)死JavaScript的靈活性但同樣具有那么優(yōu)秀的OO)。看看現(xiàn)在大多數(shù)流行不流行的開(kāi)發(fā)框架都是基于Java這種強(qiáng)大的能力來(lái)實(shí)現(xiàn)的,它讓大家可以編寫(xiě)更加通用的程序,也是為什么它在系統(tǒng)程序(包括一些框架、工具甚至服務(wù)器等)中使用這么廣泛并都作為核心技術(shù);但是在編寫(xiě)應(yīng)用程序的過(guò)程中應(yīng)該減少反射的使用,因?yàn)榉瓷淦鋵?shí)是很脆弱的,編譯器很難幫助大家發(fā)現(xiàn)程序中的錯(cuò)誤,任何錯(cuò)誤都到了運(yùn)行時(shí)才被發(fā)現(xiàn),并導(dǎo)致一些莫名其妙的異常。說(shuō)起莫名其妙其實(shí)不是說(shuō)反射功能不夠健壯或有問(wèn)題,而是出現(xiàn)錯(cuò)誤后很難跟蹤和排查,給開(kāi)發(fā)和維護(hù)帶來(lái)很大困難。
還有一點(diǎn)也很重要,反射比直接調(diào)用慢,這個(gè)要時(shí)刻記住。所以應(yīng)該用接口來(lái)實(shí)現(xiàn)回調(diào)之類的功能而不是反射。
其實(shí)這些只是繼承技巧的冰山一角而已,每個(gè)人在設(shè)計(jì)過(guò)程中都會(huì)總結(jié)出自己的經(jīng)驗(yàn)。
總的來(lái)說(shuō)我們應(yīng)該用理論來(lái)指導(dǎo)實(shí)踐,而在實(shí)踐中總結(jié)出理論!
posted on 2007-04-12 01:51
cresposhi 閱讀(2088)
評(píng)論(12) 編輯 收藏