熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

Java模式設計之單例模式(二)

2013-11-23 19:53:58  來源: Java高級技術 

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

  使用單例模式的條件

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

  在一個系統要求一個類只有一個實例時才應當使用單例模式反過來說如果一個類可以有幾個實例共存那麼就沒有必要使用單例類但是有經驗的讀者可能會看到很多不當地使用單例模式的例子可見做到上面這一點並不容易下面就是一些這樣的情況

  例子一

  問我的一個系統需要一些全程變量學習了單例模式後我發現可以使用一個單例類盛放所有的全程變量請問這樣做對嗎?

  答這樣做是違背單例模式的用意的單例模式只應當在有真正的單一實例的需求時才可使用

  一個設計得當的系統不應當有所謂的全程變量這些變量應當放到它們所描述的實體所對應的類中去將這些變量從它們所描述的實體類中抽出來 放到一個不相干的單例類中去會使得這些變量產生錯誤的依賴關系和耦合關系

  例子二

  問我的一個系統需要管理與數據庫的連接學習了單例模式後我發現可以使用一個單例類包裝一個Connection 對象並在finalize()方法中關閉這個Connection 對象這樣的話在這個單例類的實例沒有被人引用時這個finalize() 對象就會被調用因此Connection 對象就會被釋放這多妙啊

  答這樣做是不恰當的除非有單一實例的需求不然不要使用單例模式在這裡Connection 對象可以同時有幾個實例共存不需要是單一實例

  單例模式有很多的錯誤使用案例都與此例子相似它們都是試圖使用單例模式管理共享資源的生命周期這是不恰當的

  單例類的狀態

  有狀態的單例類

  一個單例類可以是有狀態的(stateful)一個有狀態的單例對象一般也是可變(mutable) 單例對象

  有狀態的可變的單例對象常常當做狀態庫(repositary)使用比如一個單例對象可以持有一個int 類型的屬性用來給一個系統提供一個數值惟一的序列號碼作為某個販賣系統的賬單號碼當然一個單例類可以持有一個聚集從而允許存儲多個狀態

  沒有狀態的單例類

  另一方面單例類也可以是沒有狀態的(stateless) 僅用做提供工具性函數的對象既然是為了提供工具性函數也就沒有必要創建多個實例因此使用單例模式很合適一個沒有狀態的單例類也就是不變(Immutable) 單例類 關於不變模式讀者可以參見本書的不變(Immutable )模式一章

  多個JVM 系統的分散式系統

  EJB 容器有能力將一個EJB 的實例跨過幾個JVM 調用由於單例對象不是EJB因此單例類局限於某一個JVM 中換言之如果EJB 在跨過JVM 後仍然需要引用同一個單例類的話這個單例類就會在數個JVM 中被實例化造成多個單例對象的實例出現一個JEE應用系統可能分布在數個JVM 中這時候不一定需要EJB 就能造成多個單例類的實例出現在不同JVM 中的情況

  如果這個單例類是沒有狀態的那麼就沒有問題因為沒有狀態的對象是沒有區別的但是如果這個單例類是有狀態的 那麼問題就來了舉例來說如果一個單例對象可以持有一個int 類型的屬性用來給一個系統提供一個數值惟一的序列號碼作為某個販賣系統的賬單號碼的話用戶會看到同一個號碼出現好幾次

  在任何使用了EJBRMI 和JINI 技術的分散式系統中應當避免使用有狀態的單例模式

  多個類加載器

  同一個JVM 中會有多個類加載器當兩個類加載器同時加載同一個類時會出現兩個實例在很多JEE 服務器允許同一個服務器內有幾個Servlet 引擎時每一個引擎都有獨立的類加載器經有不同的類加載器加載的對象之間是絕緣的

  比如一個JEE 系統所在的JEE 服務器中有兩個Servlet 引擎一個作為內網給公司的網站管理人員使用另一個給公司的外部客戶使用兩者共享同一個數據庫兩個系統都需要調用同一個單例類如果這個單例類是有狀態的單例類的話那麼內網和外網用戶看到的單例對象的狀態就會不同除非系統有協調機制不然在這種情況下應當盡量避免使用有狀態的單例類


From:http://tw.wingwit.com/Article/program/Java/gj/201311/27644.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.