kapok

          垃圾桶,嘿嘿,我藏的這么深你們還能找到啊,真牛!

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            455 隨筆 :: 0 文章 :: 76 評(píng)論 :: 0 Trackbacks

          http://firebody.blogbus.com/logs/2004/08/338549.html

          轉(zhuǎn)自:javaeye論壇      作者:potian

          說明:這些帖子都是在討論工廠模式,容器配置,構(gòu)造函數(shù)產(chǎn)生對(duì)象的方式各自優(yōu)缺時(shí)的回帖。很不錯(cuò)!感謝potian!!!

          除了靜態(tài)方法對(duì)具體子類的直接依賴問題之外,對(duì)象的產(chǎn)生封裝在對(duì)象內(nèi)部也是一個(gè)很奇怪的想法,如果在不同情況下,例如需要同步或者需要lazy等等的話,你必須針對(duì)修改你的代碼,實(shí)際上我們最關(guān)心的是能夠在不同場(chǎng)合使用同一個(gè)對(duì)象的業(yè)務(wù)邏輯,而你這樣做的話會(huì)緊緊因?yàn)槲覀冃枰煌膶?duì)象創(chuàng)建方法而修改對(duì)象的代碼,這是非常不智的,這也是singleton被視作evil的重要原因之一。(例如singleton,有時(shí)候我們希望使用超類的實(shí)例,有時(shí)候希望使用子類的實(shí)例,有的時(shí)候我們希望產(chǎn)生單個(gè),有的時(shí)候需要產(chǎn)生多個(gè)[取singleton單控制點(diǎn)的含義],有的時(shí)候需要同步,有的時(shí)候不需要同步,在集群的情況我們甚至可能需要數(shù)據(jù)庫(kù)來實(shí)現(xiàn)唯一化控制,有時(shí)候希望緩存,有的時(shí)候不需要緩存,有的時(shí)候希望增強(qiáng),有的時(shí)候希望采用動(dòng)態(tài)代理產(chǎn)生。所以一般來說,我們希望在一個(gè)系統(tǒng)內(nèi)部最多只有一個(gè)入口的singleton,而我們也往往也不打算在其它不同的場(chǎng)合重用這個(gè)singleton)。

          代碼的重用是對(duì)他業(yè)務(wù)邏輯的重用,這正是對(duì)象的核心價(jià)值。所以如同charon所說的,相對(duì)而言,我們往往不在乎組裝代碼的重用性,而是追求業(yè)務(wù)代碼本身可以被按照不同的組裝方式使用,例如既可以在EJB下,也可以在普通的Java應(yīng)用程序中,既可以作為遠(yuǎn)程傳輸?shù)膶?duì)象,因此,我們往往不會(huì)去強(qiáng)制對(duì)象構(gòu)造和產(chǎn)生的方式(例如由EJB容器產(chǎn)生,由IOC容器產(chǎn)生、有抽象工廠產(chǎn)生,或者直接由new產(chǎn)生),相反,是把對(duì)象的產(chǎn)生交給外部負(fù)責(zé),這樣才能達(dá)到在不同場(chǎng)合下對(duì)象最大的可重用性。說個(gè)簡(jiǎn)單的,如果對(duì)象的構(gòu)造方法是私有的,那么現(xiàn)在的很多框架(例如hibernate,JavaBean,EJB等等你就根本不能使用了).這也是現(xiàn)在認(rèn)為POJO比有特殊要求的對(duì)象更好的原因,因?yàn)槿魏我环N框架和技術(shù)都可以自由選擇自己的方式來創(chuàng)建對(duì)象。

          所有創(chuàng)建型設(shè)計(jì)模式和IoC容器的使用正是基于這樣的假設(shè)的,只有對(duì)象把構(gòu)造的責(zé)任交給外部來實(shí)現(xiàn),那么我們才能有效地隱藏對(duì)象創(chuàng)建的時(shí)機(jī)、方式、方法,給不修改對(duì)象本身的代碼而能夠使用不同的對(duì)象創(chuàng)建方式(包括使用子類,替代類)提供了前提,從而提高對(duì)象實(shí)現(xiàn)業(yè)務(wù)邏輯的在不同場(chǎng)合的可重用性。所以不是說一定要用IOC容器或者用抽象工廠,而是可以用這些方法,也可以不用這種方法。而就抽象工廠和IoC容器本身而言,通過它們各自的封裝,可以進(jìn)一步實(shí)現(xiàn)對(duì)不同具體實(shí)現(xiàn)子類的解綁,就更加好了。如果有一天你不想用Pico或者不想用抽象工廠,你可以選擇其他更加合適的方法來實(shí)現(xiàn)解綁。而這個(gè)責(zé)任不應(yīng)該交給對(duì)象自己來實(shí)現(xiàn),因?yàn)槲覀兏緹o法預(yù)料這個(gè)對(duì)象將會(huì)以什么樣的方式被構(gòu)造出來,在什么時(shí)候構(gòu)造出來,需要依賴什么其它外部機(jī)制構(gòu)造出來(例如可能依賴數(shù)據(jù)庫(kù),或者依賴串行化),這最好是有外部使用這個(gè)對(duì)象的環(huán)境來決定

          最終,我們希望能夠讓對(duì)象的創(chuàng)建、對(duì)象的銷毀完全脫離對(duì)象的使用,垃圾收集器已經(jīng)為我們提供VM級(jí)別的支持,而抽象工廠和工廠方法以及其它構(gòu)造型設(shè)計(jì)模式,IoC從模式和框架的角度給我們另一半。

          你這個(gè)已經(jīng)是每次返回一個(gè)新的對(duì)象了,我要每次得到同一對(duì)象,我該怎么辦,你是不是叫我重新再在上面包一個(gè)類,把第一次取到的對(duì)象緩存起來,以后每次去取那個(gè)對(duì)象?這個(gè)時(shí)候你每次new一個(gè)還有什么意義,你說可以把它改成單個(gè),那我原先在用的代碼怎么辦?

          再?gòu)?fù)雜一點(diǎn),如果是需要在集群的服務(wù)器之間保持singleton,有的時(shí)候我需要用數(shù)據(jù)庫(kù)來持久對(duì)象狀態(tài),通過數(shù)據(jù)庫(kù)來保持唯一性,那你這份代碼需要依賴于JDBC,這個(gè)時(shí)候如果一個(gè)普通的應(yīng)用程序是不是也要依賴于JDBC?

          區(qū)別在于你的代碼是放在本類里面的,你這個(gè)類構(gòu)造會(huì)直接依賴于你的環(huán)境和當(dāng)前的假設(shè),別人根本沒辦法重用你的類

          構(gòu)造函數(shù)為什么沒有這些缺陷,因?yàn)槲覀兛梢酝ㄟ^另外一個(gè)類來實(shí)現(xiàn)和不同環(huán)境的結(jié)合,而我們正在談?wù)摰倪@個(gè)類本身可以在任何地方使用而不需要修改任何代碼.這是非常重要的,這是重用的基礎(chǔ),從我們談的范圍內(nèi)來說,如果對(duì)照OCP,那么它是C,一旦關(guān)閉,永不修改。構(gòu)造函數(shù)為什么沒有這個(gè)問題,因?yàn)樗约翰粚?duì)任何構(gòu)造自己的方法作出額外的假設(shè)(構(gòu)造函數(shù)是最最近基本的假設(shè)了),而把構(gòu)造的方法、意圖和時(shí)機(jī)完全交給了外部,如果對(duì)照OCP,那么它是O。除非你的靜態(tài)方法永遠(yuǎn)等同于new,不然的話,你任何一種實(shí)現(xiàn)方式都是對(duì)可能的構(gòu)造方式進(jìn)行無意義的假設(shè),會(huì)限制其他場(chǎng)合對(duì)你這份代碼重用的可能性,而如果永遠(yuǎn)等于new,那你這個(gè)靜態(tài)方法還有什么用。

          舉例來說,假設(shè)有3個(gè)應(yīng)用,對(duì)一個(gè)對(duì)象需要三種不同的構(gòu)造方法,一個(gè)需要proxy以實(shí)現(xiàn)攔截,一個(gè)需要普通的java類做測(cè)試,另一個(gè)需要從數(shù)據(jù)庫(kù)里面讀取以保持集群之間的唯一性,我只需要對(duì)不同的環(huán)境寫不同的工廠,而不需要去改你那個(gè)嵌在業(yè)務(wù)代碼中的靜態(tài)方法,即使改了也不能同時(shí)重用于三個(gè)場(chǎng)合,你這個(gè)時(shí)候告訴我這是外部設(shè)計(jì)的決策. 和你的實(shí)現(xiàn)細(xì)節(jié)無關(guān),我可以在外面去包一個(gè)類,那我要你那個(gè)靜態(tài)方法干什么,這個(gè)靜態(tài)方法里面到底是返回proxy還是普通java對(duì)象還是從數(shù)據(jù)庫(kù)里面讀取,任何一個(gè)都沒有意義

          總而言之,任何在本類內(nèi)部假設(shè)自己將被如何、何時(shí)、以何種方式進(jìn)行構(gòu)造的代碼是極其不利于重用的(例如singleton就是一種限制重用的方法,只不過它由他自己適合的環(huán)境,因?yàn)槿魏蜗到y(tǒng)里面肯定有一些類是可以重用,而有一些是特定于某個(gè)應(yīng)用的)。因?yàn)槟氵m合了一種環(huán)境的構(gòu)造,必然會(huì)產(chǎn)生對(duì)另一種狀況的不適合,所以最好的方式是什么也不假設(shè),把如何構(gòu)造的責(zé)任傳遞給另外一個(gè)類或者框架,那個(gè)類可以結(jié)合具體的重用場(chǎng)合實(shí)現(xiàn)構(gòu)造,緩存,單件化,動(dòng)態(tài)代理等等它希望做的任何動(dòng)作。

          面向?qū)ο蟮闹行狞c(diǎn)是職責(zé)分離和變化頻率的分離,對(duì)一個(gè)希望被重用的對(duì)象來說,它的業(yè)務(wù)代碼是它變化頻率較低的部分(這是重用的基本假設(shè)),而由于目前各種不用容器、測(cè)試、分布式計(jì)算、事務(wù)處理等等場(chǎng)合的需要,它如何被構(gòu)造的可能性則是一個(gè)比它本身業(yè)務(wù)邏輯變化率高得多的東西,這兩種職責(zé)必須被分離。


          至于你這種設(shè)計(jì)方法完全依賴于子類和繼承上的困難就更不用談了。你說你的大多數(shù)類不讓繼承,OO最重要的概念就是差異編程和增量編程,這是提高內(nèi)外部質(zhì)量、提高生產(chǎn)率的核心思想,如果沒有記錯(cuò)的話,《面向?qū)ο筌浖?gòu)造》第一章里面就明確地提出了幾個(gè)重要的內(nèi)外部指標(biāo),也是整個(gè)OO思想的軟件工程基礎(chǔ)。


          posted on 2005-05-23 23:32 笨笨 閱讀(415) 評(píng)論(0)  編輯  收藏 所屬分類: J2EEALL軟件工程和項(xiàng)目管理
          主站蜘蛛池模板: 安新县| 西平县| 闽清县| 二连浩特市| 呼伦贝尔市| 莱阳市| 万源市| 白山市| 林口县| 东莞市| 汝阳县| 涡阳县| 鄂尔多斯市| 桐城市| 桓仁| 资阳市| 南城县| 裕民县| 清远市| 磴口县| 偏关县| 西乡县| 新密市| 涞源县| 那坡县| 哈巴河县| 桂东县| 吴堡县| 射阳县| 隆昌县| 宜兰县| 长泰县| 枣庄市| 仁寿县| 清镇市| 天柱县| 古田县| 滁州市| 临漳县| 澜沧| 德昌县|