隨筆 - 81  文章 - 1033  trackbacks - 0
          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          在浮躁的年代里,我們進(jìn)取心太切,患得患失;虛榮心太強(qiáng),戰(zhàn)戰(zhàn)兢兢。一心爭(zhēng)強(qiáng)好勝,惟恐榜上無名。
          I think I can fly , and flying like a bird !
          程序員一名,已售出,缺貨中!

          我的郵件聯(lián)系方式

          用且僅用于MSN

          博客點(diǎn)擊率
          free web counter
          free web counter

          常用鏈接

          留言簿(36)

          隨筆檔案

          搜索

          •  

          積分與排名

          • 積分 - 187315
          • 排名 - 309

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜


                OO經(jīng)過這么多年的錘煉和考驗(yàn)證明是極好的,雖然也有些的人提出一些反面的意見,證明時(shí)代在發(fā)展、進(jìn)步大家需要更先進(jìn)的設(shè)計(jì)方法,不過OO終歸是目前應(yīng)用最為廣泛也最為適用的程序設(shè)計(jì)方法學(xué)。個(gè)人覺得適用最為重要,畢竟OO是能夠很好解決大多數(shù)復(fù)雜系統(tǒng)設(shè)計(jì)的。不過同時(shí)OO也讓設(shè)計(jì)者陷入一個(gè)兩難的境地。一來容易設(shè)計(jì)過輕,也就是設(shè)計(jì)的不夠,發(fā)揮不了OO的強(qiáng)大和精妙之處,面向過程和面向?qū)ο蟮膴A雜反而使得實(shí)現(xiàn)者摸不著頭腦非常痛苦(很多時(shí)候這里指的設(shè)計(jì)者和實(shí)現(xiàn)著會(huì)是同一個(gè)人);二來容易設(shè)計(jì)過度,讓OO從一個(gè)手中的工具變成了一塊腳下的石頭,讓實(shí)現(xiàn)者工作起來異常的不順利,覺得做了很多脫了褲子放屁的事情(請(qǐng)容許我的粗魯,因?yàn)槲以僖舱也坏奖冗@個(gè)更好的比喻了)。

                要解決這些問題往往需要經(jīng)驗(yàn)的積累和技巧的總結(jié),知道OO理論的人不少,真正在設(shè)計(jì)中運(yùn)用的好的確實(shí)不多。當(dāng)然OO設(shè)計(jì)中最最重要的一個(gè)部分就是繼承了,下面列舉一些常見的繼承設(shè)計(jì)技巧,讀過《Core Java》的人可能對(duì)它們非常熟悉,我結(jié)合我自己的理解做一些說明,也當(dāng)作一個(gè)學(xué)習(xí)。當(dāng)然不是記住了這些所謂的技巧就學(xué)會(huì)了繼承設(shè)計(jì),總的來講設(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)樵谶@種作用域的作用下子類可以輕松的直接訪問超類中相應(yīng)的域,可能也覺得這是理所當(dāng)然的事情,因?yàn)榧热辉谧宇愔欣^承了這個(gè)域而不能直接使用它還需要使用super關(guān)鍵字來調(diào)用超類方法去訪問往往顯得很別扭和難看。但是protected機(jī)制會(huì)帶來很嚴(yán)重的安全問題,第一,因?yàn)樽宇惣鲜菬o限制的,任何人都可以由一個(gè)類派生出另外一個(gè)子類,并編寫代碼直接訪問protected的實(shí)例域,從而破壞封裝性;第二,在Java中同一個(gè)包中的所有類都可以訪問protected域,而不管它是否為這個(gè)類的子類。

                所以推薦在盡可能的情況下把域設(shè)置為私有,不允許外部直接訪問甚至修改。但其實(shí)很多初學(xué)者,包括一些編程老手都沒辦法理解和接受這種做法。我個(gè)人認(rèn)為如果OO失去了封裝性就好比失去了靈魂的空殼,沒有了什么意義,反而變成累贅而已。


          3.  使用繼承實(shí)現(xiàn)is-a關(guān)系

                如果拋開所謂的設(shè)計(jì)思想來看,實(shí)現(xiàn)繼承最基本的目的就是節(jié)省代碼量,并且很容易就做到。但這樣往往很多人會(huì)濫用繼承,純粹為了節(jié)約代碼而節(jié)約代碼,而沒有顧及超類與子類的關(guān)系導(dǎo)致在實(shí)現(xiàn)其他相關(guān)問題的時(shí)候帶來很多麻煩,反而會(huì)多寫很多代碼,撿了芝麻丟了西瓜。

                繼承應(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)系,但子類從超類繼承來的某些方法對(duì)于子類是沒有意義的,甚至是實(shí)現(xiàn)錯(cuò)誤功能的,這個(gè)時(shí)候應(yīng)該取消繼承關(guān)系,因?yàn)檫@相當(dāng)?shù)奈kU(xiǎn)?;蛘呖梢赃x擇重新審視你的設(shè)計(jì)。


          5.  在覆蓋方法的時(shí)候,不要改變預(yù)期的行為

                結(jié)合上面4中的觀點(diǎn),有些人可能會(huì)說這個(gè)很簡(jiǎn)單,把意義不同的方法在子類中重寫,或者干脆什么也不做,也或者拋出一個(gè)異常不久解決了,so easy!其實(shí)這樣也是違背OO思想的,應(yīng)該盡量保持覆蓋方法的預(yù)期行為,只可能因?yàn)楦髯缘臉I(yè)務(wù)含義而改變實(shí)現(xiàn)方式,但是語義和行為是要保證的,就好像超類有個(gè)方法名字叫add是用來做加法的,但是你一定要極端的在子類中重寫了它,里面的代碼偷偷實(shí)現(xiàn)了一個(gè)減法,這種做法的危險(xiǎn)我想很容易理解。為什么說是偷偷的,因?yàn)榭赡苤挥心阒肋@里是做了減法,或者說幾個(gè)星期后你自己都認(rèn)為這個(gè)方法實(shí)現(xiàn)的是一個(gè)加法運(yùn)算!


          6.  使用多態(tài),而非類型信息

                很多時(shí)候需要判斷當(dāng)前對(duì)象的類型來執(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)性來處理。這個(gè)時(shí)候應(yīng)該定義一個(gè)方法放置在這兩個(gè)類的超類或者接口中,然后就可以調(diào)用

          1 x.action();

                讓語言提供的多態(tài)性自己去找應(yīng)該調(diào)用那個(gè)類的方法來實(shí)現(xiàn)。是不是像極了某種模式:)


          7.  不要過多的使用反射

                個(gè)人覺得Java擁有了反射機(jī)制簡(jiǎn)直就是太強(qiáng)大了,在運(yùn)行時(shí)能夠查看甚至修改、調(diào)用域和方法極大的提高了程序?qū)崿F(xiàn)的靈活性和技巧性。以至于我甚至有一段時(shí)間把Java當(dāng)作JavaScript來玩(愛死JavaScript的靈活性但同樣具有那么優(yōu)秀的OO)。看看現(xiàn)在大多數(shù)流行不流行的開發(fā)框架都是基于Java這種強(qiáng)大的能力來實(shí)現(xiàn)的,它讓大家可以編寫更加通用的程序,也是為什么它在系統(tǒng)程序(包括一些框架、工具甚至服務(wù)器等)中使用這么廣泛并都作為核心技術(shù);但是在編寫應(yīng)用程序的過程中應(yīng)該減少反射的使用,因?yàn)榉瓷淦鋵?shí)是很脆弱的,編譯器很難幫助大家發(fā)現(xiàn)程序中的錯(cuò)誤,任何錯(cuò)誤都到了運(yùn)行時(shí)才被發(fā)現(xiàn),并導(dǎo)致一些莫名其妙的異常。說起莫名其妙其實(shí)不是說反射功能不夠健壯或有問題,而是出現(xiàn)錯(cuò)誤后很難跟蹤和排查,給開發(fā)和維護(hù)帶來很大困難。

                還有一點(diǎn)也很重要,反射比直接調(diào)用慢,這個(gè)要時(shí)刻記住。所以應(yīng)該用接口來實(shí)現(xiàn)回調(diào)之類的功能而不是反射。




                其實(shí)這些只是繼承技巧的冰山一角而已,每個(gè)人在設(shè)計(jì)過程中都會(huì)總結(jié)出自己的經(jīng)驗(yàn)。

                總的來說我們應(yīng)該用理論來指導(dǎo)實(shí)踐,而在實(shí)踐中總結(jié)出理論!
          posted on 2007-04-12 01:51 cresposhi 閱讀(2093) 評(píng)論(12)  編輯  收藏

          FeedBack:
          # re: Core Java之OO繼承設(shè)計(jì)技巧[未登錄] 2007-04-12 08:57 阿蜜果
          總結(jié)得不錯(cuò)!  回復(fù)  更多評(píng)論
            
          # re: Core Java之OO繼承設(shè)計(jì)技巧 2007-04-12 10:18 BeanSoft
          兄弟改行做培訓(xùn)吧....  回復(fù)  更多評(píng)論
            
          # re: Core Java之OO繼承設(shè)計(jì)技巧 2007-04-12 10:21 cresposhi
          我也有這種想法啊。。。
          我們來搞個(gè)業(yè)界領(lǐng)先的Java培訓(xùn)機(jī)構(gòu)列,呵呵  回復(fù)  更多評(píng)論
            
          # re: Core Java之OO繼承設(shè)計(jì)技巧 2007-04-12 10:23 劉甘泉
          繼承會(huì)造成基類的脆弱性,所以能不用繼承最好不用。。。  回復(fù)  更多評(píng)論
            
          # re: Core Java之OO繼承設(shè)計(jì)技巧 2007-04-12 10:30 cresposhi
          @劉甘泉
          不用繼承用接口嗎?我這里不單指Java中的概念
          請(qǐng)甘泉兄指教  回復(fù)  更多評(píng)論
            
          # re: Core Java之OO繼承設(shè)計(jì)技巧 2007-04-12 10:50 junglesong
          >>不要使用受保護(hù)的域?

          這句話應(yīng)該改寫為"如果一個(gè)成員不是為了繼承而設(shè)計(jì),不要使用protected而使用private".


          <<代碼大全2>>中的關(guān)于類質(zhì)量的觀點(diǎn)也值得推薦:
          硬性規(guī)定:
          1.類層次不宜超過三層.
          2.類成員數(shù)量不宜超過7個(gè),如果全是簡(jiǎn)單數(shù)據(jù)類型最多9個(gè),有其它類的話限制為5個(gè),否則需要分解成更小的類.
          3.避免創(chuàng)建萬能類
          4.消除不必要的成員.
          5.消除無關(guān)精要的類.
          6.避免用動(dòng)詞命名類.

          抽象:
          1.類是否有一個(gè)中心目的.
          2.類的命名是否表現(xiàn)了其中心目的.
          3.類的接口是否展現(xiàn)了一致的抽象.
          4.類的接口是否讓人明白了知道該如何使用它.
          5.類的接口是否足夠抽象,使使用者不必顧慮它是如何進(jìn)行服務(wù)的.
          6.類提供的服務(wù)是否足夠完整,能讓其它類無須動(dòng)用其內(nèi)部數(shù)據(jù).
          7.是否已經(jīng)盡量分解.
          8.在修改類是是否維持了接口的完整性.

          封裝:
          1.是否把類成員的可訪問性降至最小.
          2.是否避免暴露類中的數(shù)據(jù)成員.
          3.類是否已經(jīng)盡可能的對(duì)其它類隱藏了實(shí)現(xiàn)細(xì)節(jié).
          4.類是否不依賴其它類,它是松耦合的嗎?

          http://junglesong.yculblog.com  回復(fù)  更多評(píng)論
            
          # re: Core Java之OO繼承設(shè)計(jì)技巧 2007-04-12 11:26 cresposhi
          @junglesong
          我覺得即使是為了繼承而設(shè)計(jì),也不應(yīng)該使用protected。原因是因?yàn)榧热欢x在超類中的域,它的訪問規(guī)則應(yīng)該由超類來關(guān)心和處理,不應(yīng)該授權(quán)給子類直接干涉,這樣既破壞了封裝性也不利于維護(hù)。
          特別是protected作用域還可以本包訪問,這樣就給了更多其他對(duì)象修改本類對(duì)象狀態(tài)的機(jī)會(huì),相當(dāng)危險(xiǎn)。  回復(fù)  更多評(píng)論
            
          # re: Core Java之OO繼承設(shè)計(jì)技巧 2007-04-12 14:43 kirari_wxy
          模式應(yīng)用有很多矛盾的地方,度的把握很難,不過四人幫的設(shè)計(jì)模式還是經(jīng)典的。關(guān)于類庫的設(shè)計(jì)我個(gè)人比較欣賞只有樹葉才是實(shí)現(xiàn)類的做法,其他都是接口和抽象類,至少ocp是最基礎(chǔ)的一條。protected應(yīng)該去掉。。  回復(fù)  更多評(píng)論
            
          # re: Core Java之OO繼承設(shè)計(jì)技巧 2007-04-12 22:59 軒朗=maninred
          《Core Java》中提到的OO設(shè)計(jì)思想并不多,更多的是對(duì)JDK中的API的示例。關(guān)于OO的設(shè)計(jì)思想建議你看看Robert C.Martin《敏捷軟件開發(fā)》,書中提到的OO設(shè)計(jì)原則是經(jīng)過了多年業(yè)界OO實(shí)踐得到的?!禖ore Java》中的代碼用來練習(xí)重構(gòu)手法還差不多。

          這篇文章開頭說到的OO過度設(shè)計(jì)和OO不足其實(shí)用K.Back的TDD就可以比較好的解決。  回復(fù)  更多評(píng)論
            
          # re: Core Java之OO繼承設(shè)計(jì)技巧 2007-04-13 12:41 cresposhi
          TDD?倒是一直都沒機(jī)會(huì)真正領(lǐng)略它的風(fēng)采。。。  回復(fù)  更多評(píng)論
            
          # re: Core Java之OO繼承設(shè)計(jì)技巧 2007-04-13 12:43 cresposhi
          @軒朗=maninred
          《Core Java》確實(shí)不是一本專門講OO的書。。。只是看到作者總結(jié)的這么幾點(diǎn)自己的心得覺得比較通用和好用,所以拿來分析一把
          要真正了解OO設(shè)計(jì)方法確實(shí)要寫好幾本數(shù)。。。  回復(fù)  更多評(píng)論
            
          # re: Core Java之OO繼承設(shè)計(jì)技巧 2007-05-08 19:56 咖啡屋的鼠標(biāo)
          個(gè)人認(rèn)為抽象類才是為繼承而設(shè)計(jì)的,普通類不是。而能用接口的盡量還是不使用抽象類。
          >>>>>>
          最近發(fā)現(xiàn)TDD很容易造成設(shè)計(jì)欠賬,相對(duì)與過度設(shè)計(jì),設(shè)計(jì)欠賬也是不好的。想要用好TDD還得修煉啊。  回復(fù)  更多評(píng)論
            

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 噶尔县| 上犹县| 且末县| 贵定县| 定兴县| 张掖市| 焦作市| 西林县| 衢州市| 利辛县| 惠东县| 铜梁县| 合阳县| 藁城市| 红桥区| 桦川县| 文成县| 宁武县| 涿鹿县| 西和县| 札达县| 龙口市| 肇州县| 哈密市| 龙州县| 潜山县| 基隆市| 丰都县| 宜兴市| 深水埗区| 盐池县| 贵溪市| 乐山市| 社会| 枣阳市| 宜宾市| 靖远县| 宜黄县| 柳江县| 德昌县| 百色市|