我的隱式生活(My Implicit Life)

          繼續(xù)搞“對象”,玩OO.

          首頁 新隨筆 聯(lián)系 聚合 管理
            11 Posts :: 1 Stories :: 39 Comments :: 0 Trackbacks

          創(chuàng)建和銷毀對象

          重點關(guān)注對象的創(chuàng)建和銷毀:什么時候、如何創(chuàng)建對象,什么時候、什么條件下應(yīng)該避免創(chuàng)建對象,如何保證對象在合適的方式下被銷毀,如何在銷毀對象之前操作一些必須的清理行為。

          嘗試用靜態(tài)工廠方法代替構(gòu)造器

          如果一個 client 要實例化一個對象來使用,傻 b 都知道應(yīng)該先調(diào)用類的構(gòu)造器來 new 一個對象,之后再調(diào)用相應(yīng)的方法。除了這個方式, Java Effective 還建議了另一種方法:用靜態(tài)工廠方法來提供一個類的實例。以下的例子不反映兩者的優(yōu)劣,只是反映兩者在代碼實現(xiàn)上的不同,優(yōu)劣之后再談:

          假設(shè)咱們要一個顏色為黑色、長度為 50cm 的錘子,自然就用構(gòu)造器創(chuàng)建一個

          Hammer myHammer =? new Hammer(Color.BLACK, 50);

          而用靜態(tài)工廠方法來實例化一個對象,如下

          Hammer myHammer = Hammer.factory(Color.BLACK,50);

          也可以用專門的一個工廠類來實例化

          Hammer myHammer = Toolkit.factory(“Hammer”, Color.BLACK,50);??

          單純從上面的代碼上看,真的只有傻 b 才會選擇靜態(tài)工廠的方法,完全就是多此一舉,直接 new 又快又爽,搞這么麻煩做莫斯(武漢話“什么”的意思)?

          別急,別急,你急個莫 b (武漢粗話:基本就是“你急個毛”的意思)?

          下面就說說用靜態(tài)工廠代替構(gòu)造器的好處( advantage )和不好處( disadvantage )。

          第一個好處,講你都不信,行家們認(rèn)為,構(gòu)造器有一個不好的地方就是:這個方法的簽名( signture )太固定了。

          構(gòu)造器的名字是固定的,生個 Hammer ,構(gòu)造器的名字就是 Hammer (……),唯一能變化的地方就是參數(shù),假設(shè)我的這個錘子有兩個很變態(tài)的構(gòu)造需要:

          1 :第一個參數(shù)是顏色( Color 型),第二個參數(shù)是錘子頭的重量( int 型)。

          Hammer Color c, int kg {

          //remainder omited

          }

          2 :第一個參數(shù)是顏色( Color 型),第二個參數(shù)是錘子的長度( int 型)。

          Hammer Color c, int cm {

          //remainder omited

          }

          感覺滿足需要了,但是細(xì)心一看,完了,構(gòu)造器的參數(shù)列表類型重復(fù)了,肯定編譯通不過,這是面向?qū)ο髽?gòu)造器天生的缺陷——唯一的變化就是參數(shù),參數(shù)都分辨不了,就真的分辨不了。

          而另外就算參數(shù)能分辨的了,構(gòu)造器一多,它的參數(shù)一多,您根本就不知道每個參數(shù)是用來干什么的,只能去查閱文檔,在您已經(jīng)眼花繚亂的時候再去查文檔,一個一個的對,折磨人的活。

          這個時候,您就可以考慮用靜態(tài)工廠方法來實例化對象了。因為靜態(tài)工廠方法有一個最簡單的特點就是:他有可以變化的方法名(構(gòu)造器的名字變不了)。用名字的不同來代表不同的構(gòu)造需要,這么簡單的普通的特點在這里就是它相對于構(gòu)造器的 advantage

          如上面的錘子的例子可以這樣:

          1 Hammer.produceByWeight (Color c, int kg){

          //remainder omited

          }

          2 Hammer.produceByHeight (Color c, int cm){

          //remainder omited

          }

          這是不是一目了然多了。嗯,我是這樣認(rèn)為的。

          第二個好處,“靜態(tài)工廠方法不需要每次都真的去實例化一個對象”——其實這也是另一些優(yōu)化方法的前提。

          構(gòu)造器的每次 invoke 必定會產(chǎn)生一個新的對象,而靜態(tài)工廠方法經(jīng)過一定的控制,完全可以不用每次 invoke 都生成一個新的對象。

          為什么不每次都生成一個對象的原因就不必說了,因為原因太明顯。這個原因就是為什么要“共享”對象的原因。

          下面講講通常使用的兩種共享具體策略,也就是具體方法了:

          1 :單例模式的需要,一旦需要某個對象有單例的需要,必定對于這類對象的構(gòu)造只能用靜態(tài)工廠方法了。

          2 flyweight 模式和不變( immutable 模式的需要,這兩個模式很多時候都說一起使用的,一旦一些對象我們認(rèn)為是不變的,那自然就想拿來重用,也就說共享,而 flyweight 就是用來重用這些小粒度對象的。

          Boolean.valueOf (boolean) 方法:

          Boolean a = Boolean.valueOf (100);

          Boolean b = Boolean.valueOf (100);

          ?a,??b兩個引用都是指向同一個對象。

          這些對象都是不變的,而 valueOf 的控制就是用的 flyweight 方法。

          這種一個狀態(tài)(如上面一個數(shù)字)對應(yīng)的對象只有一個還有一個好處,就是可以直接通過比較“引用”來判斷他們是否 equel (這里的 equel 是邏輯相等的意思),以前需要 a.equels(b) ,而一旦用“ flyweight 模式和不變( immutable 模式”后,避免了產(chǎn)生多余的相同對象,用 a==b 就可以達(dá)到 a.equels(b) 的目的了。這樣當(dāng)然優(yōu)化了 performance ??

          第三個好處,其實就是工廠方法的核心好處——我把它稱為“抽象類型構(gòu)造器”。它可以為我們提供一個抽象類型的實例,同時必要的隱藏了抽象類型的具體結(jié)構(gòu)。這是 new 怎么都達(dá)不到的。

          這種模式的好處其實就是面向?qū)ο蟮淖詈诵牡暮锰帲橄蠛途唧w可以分離,一旦抽象定義好了,具體的東西可以慢慢的變化,慢慢的拓展——開閉原則。

          Collections Framework API ,都是描述集合類型的接口,也就是對于客戶端來看,只有 Collection 這個類要認(rèn)識,而實際上,實現(xiàn)這個接口的 Collection 是多種多樣的。如果要讓用戶都知道這些具體實現(xiàn)的 Collection ,就增加了復(fù)雜度。

          這時,通過一個靜態(tài)工廠方法,就可以隱藏各種 Collection 的具體實現(xiàn),而讓 Client 只使用返回的 Collection 對象就可以了。

          這里還可以加上一些權(quán)限控制,如這些實現(xiàn)只要對于工廠來講是可以訪問的,不用是 public 的,而他們只要通過 public 的工廠就可以提供給用戶。非常有利于代碼的安全。

          靜態(tài)工廠方法的第一個缺點就是:使用靜態(tài)工廠方法創(chuàng)建的類的構(gòu)造器經(jīng)常都是非公共或非 protected 的。 這樣,以后這些類就沒有辦法被繼承了。不過也有人說,不用繼承就用 composition 唄。也是!呵呵。

          靜態(tài)工廠方法的第二個缺點是:在 jdk 文檔里,這些靜態(tài)工廠方法很難跟別的靜態(tài)方法相區(qū)別。 而文檔中,構(gòu)造器是很容易看到的。

          為了一定程度解決這個問題,我們可以用一些比較特別的名字來給這類靜態(tài)工廠方法來命名。最常用的有:

          valueOf —— 用來放回跟參數(shù)“相同值”的對象。

          getInstance —— 返回一個對象的實例。單例模式中,就是返回單例對象。

          總結(jié):靜態(tài)工廠方法和構(gòu)造器都有各自的特點。最好在考慮用構(gòu)造器之前能先考慮一下靜態(tài)工廠方法,往往,后者更有用一點。如果權(quán)衡了以后也看不出那個好用一些,那就用構(gòu)造器,畢竟簡單本分多了。

          posted on 2006-07-15 12:35 marco 閱讀(638) 評論(0)  編輯  收藏 所屬分類: -=Java API=--=Java Techs=-

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


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 新化县| 北海市| 浦城县| 延津县| 巴林左旗| 讷河市| 长子县| 齐河县| 闻喜县| 依安县| 新郑市| 若尔盖县| 德清县| 商丘市| 湘乡市| 安仁县| 隆回县| 黑龙江省| 罗田县| 望奎县| 康定县| 新化县| 吉安县| 子洲县| 兰考县| 观塘区| 施秉县| 十堰市| 太保市| 绩溪县| 武清区| 闵行区| 大足县| 尼勒克县| 杭州市| 株洲县| 金堂县| 永州市| 墨竹工卡县| 南昌县| 温州市|