設計模式之第0章-單例模式(Java實現)
當當當當~首先有請最簡單的單例模式登場,先來個自我介紹吧
單例模式之自我介紹
我,單例模式(Singleton Pattern)是一個比較簡單的模式,我的定義如下:
Ensure a class has only one instance,and provide a global point of access to it.(確保其某一個類只有一個實例,而且自行實例化並向整個系統提供這個實例。)單例模式的通用類圖如下:
Singleton類稱為單例類,通過使用private的構造函數確保了在一個應用中只產生一個實例,並且是自行實例化的。
單例模式之自我分析
做人,哦不,做模式不能自滿,所以先談談我的缺點,我的缺點如下:
- 我一般沒有接口,擴展很困難,如果想擴展的話,除了修改代碼基本上沒有第二種方式。當然了,特殊情況下,我也可以實現接口、被繼承等,這個需要你們自行判斷。
- 測試不便。在並行開發中,如果你們沒有把我完成,那么是沒有辦法進行測試的。
- 還有一點,我與單一職責原則也有沖突,一個類本應實現一個邏輯,不該關心是否是單例的,是不是要單例取決於環境,但是我把單例和業務邏輯融合在一個類中了。
終於該說優點了~挺好了,比缺點可是要多的說:
- 對唯一實例的受控訪問。由於我的類封裝了我唯一的實例,所以可以嚴格控制用戶以及何時訪問它。
- 縮小名空間。我可以避免那些存儲唯一實例的全局變量污染名空間。
- 允許對操作和表示的精化。
- 允許可變數目的實例。
- 比類操作更靈活。
單例模式之實現
俗話說,說的比唱的好聽。為了證明我唱的也很好聽,接下來我就以人類的一夫一妻制來具體講解一下如何實現我的模式~一夫一妻制又稱作”單偶婚“,“個體婚”,據說一夫一妻制起源於秦始皇統一天下之后,自大秦一統天下,中國酒實行了一夫一妻制,尤其是在漢朝“罷黜百家,獨尊儒術”開始,古人嚴格執行了這一制度blablabla...(此處省略n字)。咳咳,跑題了,我們接着談一夫一妻制,哦不,單例模式,首先得有個妻子類:
1 public class Wife{ 2 3 private static final Wife wife = new Wife(); 4 private Wife(){ 5 6 } 7 public static Wife getInstance(){ 8 return wife; 9 } 10 public static void say(){ 11 System.out.println("I am Y's wife!"); 12 } 13 }
通過定義一個私有訪問權限的構造函數,可以避免被其他類new出來一個對象,而Wife自己可以new一個對象出來,其他的類對該類的訪問可以通過getInstance獲得一個對象。妻子有了,老公Y自然要出場了,其類代碼如下:
1 public class Y{ 2 public static void main(String[] args) { 3 for (int day=0; day<3;day++ ) { 4 Wife wife = Wife.getInstance(); 5 wife.say(); 6 } 7 } 8 }
運行結果如下:
I am Y's wife!
I am Y's wife!
I am Y's wife!
Y每天回家見到的妻子,都是同一個妻子,不會出現開門后,一看,呦呵,老婆怎么變了?如有此情況,請速與我聯系!
單例模式之優化OR問題
有人嫌這樣麻煩,因為無論是都使用這個類,都會創建一個instance對象,如果創建這個很耗時,比如需要連接10**9(python的10的9次方寫法)次數據庫,並且還不一定使用,那該這么辦?於是乎有“聰明人”想到如下的方法:
public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
是不是感覺很不錯,很好?這個是傳說中的懶漢模式其實這個有個很大的問題,如果是高並發情況下,可能A線程在創建實例,但是還沒獲取對象,B此時也在執行,判斷也為真,所以又獲得一個對象,如此下去,你的妻子會越來越多!沒辦法了么?不,當然有,且往下看:
1 public class Singleton { 2 private static Singleton instance; 3 private Singleton (){} 4 public static synchronized Singleton getInstance() { 5 if (instance == null) { 6 instance = new Singleton(); 7 } 8 return instance; 9 } 10 }
這種寫法確實解決了問題,但是效率么,嘖嘖,99%情況下不需要同步我會告訴你么?
奇技淫巧:單例模式之反射實現
1 public class Singleton{ 2 private static Singleton singleton; 3 static{ 4 try{ 5 class cl = class.forName(Singleton.class.getName()); 6 //獲得無參構造 7 Constructor con = cl.getDeclaredConstructor(); 8 //設置無參構造是可訪問的 9 con.setAccessible(true); 10 //產生一個實例對象 11 singleton = (Singleton)con.newInstance(); 12 } 13 catch(Exception e) 14 { 15 16 } 17 } 18 19 public static Singleton getSingleton(){ 20 return singleton; 21 } 22 }
通過獲得類構造,然后設置訪問權限,生成一個對象,然后提供外部訪問,保證內存對象單一。
以上就是我,單例模式,謝謝大家~下回就是我的大哥來做演講了,欲知后事如何,且聽下回分解。
PS:本博客歡迎轉發,但請注明博客地址及作者~
博客地址:http://www.cnblogs.com/voidy/
博客新址:http://voidy.net
<。)#)))≦