kapok

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

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            455 隨筆 :: 0 文章 :: 76 評論 :: 0 Trackbacks
          http://www.uml.org.cn/j2ee/200501241.htm


          Java模式設(shè)計之單例模式(二)
          閻宏 作者授權(quán)

            在什么情況下使用單例模式

            使用單例模式的條件

            使用單例模式有一個很重要的必要條件:

            在一個系統(tǒng)要求一個類只有一個實例時才應(yīng)當(dāng)使用單例模式。反過來說,如果一個類可以有幾個實例共存,那么就沒有必要使用單例類。但是有經(jīng)驗的讀者可能會看到很多不當(dāng)?shù)厥褂脝卫J降睦樱梢娮龅缴厦孢@一點并不容易,下面就是一些這樣的情況。

            例子一

            問:我的一個系統(tǒng)需要一些"全程"變量。學(xué)習(xí)了單例模式后,我發(fā)現(xiàn)可以使用一個單例類盛放所有的"全程"變量。請問這樣做對嗎?
           
            答:這樣做是違背單例模式的用意的。單例模式只應(yīng)當(dāng)在有真正的"單一實例"的需求時才可使用。

            一個設(shè)計得當(dāng)?shù)南到y(tǒng)不應(yīng)當(dāng)有所謂的"全程"變量,這些變量應(yīng)當(dāng)放到它們所描述的實體所對應(yīng)的類中去。將這些變量從它們所描述的實體類中抽出來, 放到一個不相干的單例類中去,會使得這些變量產(chǎn)生錯誤的依賴關(guān)系和耦合關(guān)系。

            例子二

            問:我的一個系統(tǒng)需要管理與數(shù)據(jù)庫的連接。學(xué)習(xí)了單例模式后,我發(fā)現(xiàn)可以使用一個單例類包裝一個Connection 對象,并在finalize()方法中關(guān)閉這個Connection 對象。這樣的話,在這個單例類的實例沒有被人引用時,這個finalize() 對象就會被調(diào)用,因此,Connection 對象就會被釋放。這多妙啊。

            答:這樣做是不恰當(dāng)?shù)摹3怯袉我粚嵗男枨螅蝗徊灰褂脝卫J健T谶@里Connection 對象可以同時有幾個實例共存,不需要是單一實例。

            單例模式有很多的錯誤使用案例都與此例子相似,它們都是試圖使用單例模式管理共享資源的生命周期,這是不恰當(dāng)?shù)摹?BR>  單例類的狀態(tài)

            有狀態(tài)的單例類

            一個單例類可以是有狀態(tài)的(stateful),一個有狀態(tài)的單例對象一般也是可變(mutable) 單例對象。
          有狀態(tài)的可變的單例對象常常當(dāng)做狀態(tài)庫(repositary)使用。比如一個單例對象可以持有一個int 類型的屬性,用來給一個系統(tǒng)提供一個數(shù)值惟一的序列號碼,作為某個販賣系統(tǒng)的賬單號碼。當(dāng)然,一個單例類可以持有一個聚集,從而允許存儲多個狀態(tài)。

            沒有狀態(tài)的單例類

            另一方面,單例類也可以是沒有狀態(tài)的(stateless), 僅用做提供工具性函數(shù)的對象。既然是為了提供工具性函數(shù),也就沒有必要創(chuàng)建多個實例,因此使用單例模式很合適。一個沒有狀態(tài)的單例類也就是不變(Immutable) 單例類; 關(guān)于不變模式,讀者可以參見本書的"不變(Immutable )模式"一章。

            多個JVM 系統(tǒng)的分散式系統(tǒng)

            EJB 容器有能力將一個EJB 的實例跨過幾個JVM 調(diào)用。由于單例對象不是EJB,因此,單例類局限于某一個JVM 中。換言之,如果EJB 在跨過JVM 后仍然需要引用同一個單例類的話,這個單例類就會在數(shù)個JVM 中被實例化,造成多個單例對象的實例出現(xiàn)。一個J2EE應(yīng)用系統(tǒng)可能分布在數(shù)個JVM 中,這時候不一定需要EJB 就能造成多個單例類的實例出現(xiàn)在不同JVM 中的情況。

            如果這個單例類是沒有狀態(tài)的,那么就沒有問題。因為沒有狀態(tài)的對象是沒有區(qū)別的。但是如果這個單例類是有狀態(tài)的, 那么問題就來了。舉例來說,如果一個單例對象可以持有一個int 類型的屬性,用來給一個系統(tǒng)提供一個數(shù)值惟一的序列號碼,作為某個販賣系統(tǒng)的賬單號碼的話,用戶會看到同一個號碼出現(xiàn)好幾次。
          在任何使用了EJB、RMI 和JINI 技術(shù)的分散式系統(tǒng)中,應(yīng)當(dāng)避免使用有狀態(tài)的單例模式。

            多個類加載器

            同一個JVM 中會有多個類加載器,當(dāng)兩個類加載器同時加載同一個類時,會出現(xiàn)兩個實例。在很多J2EE 服務(wù)器允許同一個服務(wù)器內(nèi)有幾個Servlet 引擎時,每一個引擎都有獨立的類加載器,經(jīng)有不同的類加載器加載的對象之間是絕緣的。

            比如一個J2EE 系統(tǒng)所在的J2EE 服務(wù)器中有兩個Servlet 引擎:一個作為內(nèi)網(wǎng)給公司的網(wǎng)站管理人員使用;另一個給公司的外部客戶使用。兩者共享同一個數(shù)據(jù)庫,兩個系統(tǒng)都需要調(diào)用同一個單例類。如果這個單例類是有狀態(tài)的單例類的話,那么內(nèi)網(wǎng)和外網(wǎng)用戶看到的單例對象的狀態(tài)就會不同。除非系統(tǒng)有協(xié)調(diào)機制,不然在這種情況下應(yīng)當(dāng)盡量避免使用有狀態(tài)的單例類。

          posted on 2005-04-18 14:40 笨笨 閱讀(187) 評論(0)  編輯  收藏 所屬分類: J2EEALL
          主站蜘蛛池模板: 邵阳市| 巩义市| 崇仁县| 晋宁县| 汤阴县| 十堰市| 滦平县| 连云港市| 西乌| 陈巴尔虎旗| 布拖县| 桃园市| 靖边县| 泾源县| 日喀则市| 承德市| 阿鲁科尔沁旗| 松原市| 涿州市| 甘肃省| 德江县| 郯城县| 清苑县| 龙陵县| 龙川县| 盘山县| 台山市| 鹤岗市| 华蓥市| 如皋市| 龙川县| 保亭| 通榆县| 惠州市| 沐川县| 海晏县| 金秀| 枣强县| 正定县| 香港| 高淳县|