???????? 今天去jdon,看了它的設(shè)計研究欄目,bang有幾篇評論單例模式的文章,聲稱“Singleton is evil”(見http://www.jdon.com/jive/article.jsp?forum=91&thread=17578),并且引用幾篇外文頁面佐證自己的觀點,其中有一篇文章更是說,單例不僅不是一種模式,而是一種反模式。??????? 下面我談?wù)勎覍卫J降目捶āV鹨环治鰡卫J降南葳澹瑤椭蠹艺_使用單例模式。(1)?陷阱一:調(diào)用函數(shù)的性能瓶頸??????? 在c++中,單例只有一種實現(xiàn)方式——LazySingleton, 實現(xiàn)如下(本文全部使用java代碼):
LazySingleton將對象的初始化推遲到調(diào)用的時候。并且為了防止多線程環(huán)境下產(chǎn)生多個實例,使用synchronized關(guān)鍵字保證函數(shù)getInstance調(diào)用的線程安全。synchronized關(guān)鍵字的存在保證了只會產(chǎn)生一個對象,但也成了多線程環(huán)境下的性能瓶頸。一個多線程的程序,到了這里卻要排隊等候成了一個單線程式的執(zhí)行流程,這在高并發(fā)環(huán)境下是不可容忍的。而c++中可以使用雙重檢查機(jī)制將這種性能問題僅僅限制在第一次構(gòu)造對象的時候,而java中不可以使用雙重檢查機(jī)制。????????但是java可以實現(xiàn)EagerSingleton,實現(xiàn)如下:
該類含有一私有屬性value,在多線程環(huán)境下不能保證value值的合理邏輯,一線程getValueByName后,馬上printValue,也有可能value的值已經(jīng)被其他線程修改。這種情況就屬于單例模式的濫用,該類根本不適合做成單例。??????? 消除非法邏輯的陷阱,可以通過將該類重構(gòu)為純粹的行為類完成。重構(gòu)后的代碼如下:
通過調(diào)用printName(String name)直接完成操作流程,將其中的私有屬性處理成過程式的參數(shù)傳遞,將該類修改成純粹的行為類。
??????? 含有私有屬性并且含有對它賦值操作的類并非都會調(diào)入該陷阱,構(gòu)造函數(shù)里進(jìn)行對私有屬性賦值不會引起非法邏輯,如下代碼
構(gòu)造函數(shù)里不必要加線程安全關(guān)鍵字也可以保證線程安全,因為類加載器是線程安全的,EagerSingleton只會在類加載的時候?qū)嵗淮危@樣不會出現(xiàn)單例模式的線程不安全,也不會造成非法邏輯。(4)陷阱四:單例陷阱的傳遞??????? 當(dāng)含有對象作為單例類的私有屬性時,陷阱不僅會出現(xiàn)在該類本身,還會傳遞到私有對象所在的類中。看如下代碼:
Powered by: BlogJava Copyright © JavaExplore