單例模式有以下特點:
1、單例類隻能有一個執行個體。
2、單例類必須自己建立自己的唯一執行個體。
3、單例類必須給所有其他對象提供這一執行個體。
單例模式確定某個類隻有一個執行個體,而且自行執行個體化并向整個系統提供這個執行個體。在計算機系統中,線程池、緩存、日志對象、對話框、列印機、顯示卡的驅動程式對象常被設計成單例。這些應用都或多或少具有資料總管的功能。每台計算機可以有若幹個列印機,但隻能有一個Printer Spooler,以避免兩個列印作業同時輸出到列印機中。每台計算機可以有若幹通信端口,系統應當集中管理這些通信端口,以避免一個通信端口同時被兩個請求同時調用。總之,選擇單例模式就是為了避免不一緻狀态,避免政出多頭。
在這裡介紹兩種單例模式:懶漢式,餓漢式
一:懶漢式單例:
聽名字就能聽出來,懶漢式,就是很懶嘛,怎麼個懶法,打比方你現在有個任務要做,老闆給你三天的期限讓你做完,你一下耍了兩天半,明天就要交任務,你迫不得已才去做。這和懶漢式很像。
下面上代碼:
1 package Singleton;
2
3 public class LanHan {
4 private static LanHan lan=null;//在這裡不初始化
5
6 private LanHan() {//讓外界不鞥調用
7 super();
8 }
9
10 public synchronized static LanHan geiObject(){//提供公共的通路方法,加上線程同步
11 if(lan==null){
12 lan=new LanHan();//迫不得已初始化對象
13 }
14 return lan;//交任務
15 }
16 }
下面我們建立一個測試類,看看這個單例模式是不是對的。。。。。
當我們試圖去通過new去建立這個類的對象的時候,是不通過的,因為我們把構造給私有化了,隻能通過我們提供的公共的方法去建立對象。
代碼如下:
1 package Singleton;
2
3 public class Test {
4
5 public static void main(String[] args) {
6 // TODO Auto-generated method stub
7
8 LanHan l1=LanHan.geiObject();
9 LanHan l2=LanHan.geiObject();
10 System.out.println(l1);
11 System.out.println(l2);
12 System.out.println(l1==l2);
13 }
14 }
我們運作,看是不是隻建立了一個對象
毫無疑問,這個是可以的。
一:餓漢式單例:
餓漢式的例子可以是這樣的,如果我現在非常非常的餓,那我看到美食會不會立馬狼吞虎咽。。。。。。。當然會。
1 package Singleton;
2
3 public class EHan {
4 private static EHan e=new EHan();//在這裡我們直接給初始化
5
6 private EHan() {
7 super();//同樣的私有
8 }
9
10 public synchronized static EHan getObject(){
11 if(e==null){//一樣的同步,一樣的如果為空才會再去初始化
12 e=new EHan();
13 }
14 return e;
15 }
16 }
在下面我們建立測試類,代碼如下:
1 package Singleton;
2
3 public class Test {
4
5 public static void main(String[] args) {
6 // TODO Auto-generated method stub
7
8 /*LanHan l1=LanHan.geiObject();
9 LanHan l2=LanHan.geiObject();
10 System.out.println(l1);
11 System.out.println(l2);
12 System.out.println(l1==l2);*/
13
14 EHan e1=EHan.getObject();
15 EHan e2=EHan.getObject();
16 System.out.println(e1);
17 System.out.println(e2);
18 System.out.println(e1==e2);
19 }
20 }
測試的結果是很明顯的:
總結:
餓漢式和懶漢式都是能實作單例的效果的:
1.在初始化方面:
餓漢就是類一旦加載,就把單例初始化完成,保證getInstance的時候,單例是已經存在的了,
而懶漢比較懶,隻有當調用getInstance的時候,才回去初始化這個單例。
2.線上程安全方面:
餓漢式天生就是線程安全的,可以直接用于多線程而不會出現問題,
懶漢式本身是非線程安全的,為了實作線程安全有幾種寫法,分别是上面的1、2、3,這三種實作在資源加載和性能方面有些差別。
3.資源加載和性能:
餓漢式在類建立的同時就執行個體化一個靜态對象出來,不管之後會不會使用這個單例,都會占據一定的記憶體,但是相應的,在第一次調用時速度也會更快,因為其資源已經初始化完成,
而懶漢式顧名思義,會延遲加載,在第一次使用該單例的時候才會執行個體化對象出來,第一次調用時要做初始化,如果要做的工作比較多,性能上會有些延遲,之後就和餓漢式一樣了。
歡迎大家一起說出自己的想法。