java語言實現創建型設計模式—單例模式


一、描述

單例模式就是確保一個類只有一個實例對象,並且在實例對象必須自動創建,對外不提供該對象的構造方法,並向整個系統提供該實例。使用單例模式相當於整個系統共用該類的實例對象,對於java中的並發訪問有重要意義。

單例模式又分為餓漢模式和飽漢模式兩種,餓漢模式就是在類加載的時候就創建和初始化該類的唯一的實例對象,而飽漢模式是系統需要用到這個類的實例的時候才創建該對象。


二、單例模式的優缺點

優點:在單列模式中,客戶端調用類的實例時,只能調用一個公共的接口,這就為整個系統提供了一個共享的對象。因為在系統內存中只存在一個對象,所以可以節約系統資源,相對於那些需要頻繁創建和銷毀的對象的類來說無疑提高了效率。而且由類自己來控制實例化過程,類就在改變實例化進程上有相應的伸縮性。

缺點:實現單例模式的類在實例化后不能被別的類繼承;而且一個類只有唯一的對象,那么這個單例類的職責就會過重,在一定程度上違背了“單一職責原則”;類的實例在初始化后就不能再更改也不適合於類的實例經常變動的場景;如果在分布式系統中,當系統中的單例類被復制到不同的虛擬機下,在每個虛擬機中都會創建一個實例對象,要分清具體哪個虛擬機下運行哪個單例對象比較困難;再者,由於單例模式中的實例是一個共享的概念,在並發訪問時需要附加代碼保證其訪問安全性。


三、源代碼

package tong.yue.day4_25;

import java.io.IOException;
/**
* 單例模式是一種非常常見的設計模式,即一個類只能有一個對象(實例),一般通過將該類的構造器私有化,來阻止在該類外創建該類的對象,並提供給外界一個唯一的對象(這個對象在該類中創建)。
* java中的單例模式常見的有兩種實現方式,一種是惡漢方式,即將該類對象用static休息並且在類加載的時候進行初始化;
* 另一種是飽漢方式,在程序中需要用到該對象的時候才初始化,一旦初始化一次就不會再重新生成該對象。
* jdk中的Runtime類其實也是一種單例模式,而且其采用的是餓漢的方式。
* @author Administrator
*
*/

public class Singleton {

public static void main(String[] args) {

//餓漢式獲取單例類的對象
Singleton_eager singleton = Singleton_eager.getInstance();
singleton.print();
//餓漢式獲取單例類的對象
Singleton_lazy singleton_lazy = Singleton_lazy.getInstance();
singleton_lazy.print();
}
}
//餓漢式單例模式,在類加載的時候創建一個對象,之后就不再重復創建
class Singleton_eager {
//聲明為static類型,在類加載的時候創建一個對象
private static Singleton_eager singleton_eager = new Singleton_eager();
private Singleton_eager(){

}

public static Singleton_eager getInstance() {
return singleton_eager;
}

public void print() {
System.out.println(singleton_eager);
}
}
//飽漢式單例模式,當程序第一次使用該類的對象時創建對象,只創建一次,之后就不再重復創建
class Singleton_lazy{
private static Singleton_lazy singleton_lazy = null;
private Singleton_lazy(){}
//單例對象的創建方法需要加上同步,因為在多線程並發訪問時要保證其訪問安全性和統一性。
public synchronized static Singleton_lazy getInstance() {
//若是第一次使用該對象,那個就創建一個,否則就使用一個已經創建好的對象
if (singleton_lazy==null) {
singleton_lazy = new Singleton_lazy();
}
return singleton_lazy;
}

public void print() {
System.out.println(singleton_lazy);
}
}

運行結果:

單例

四、總結

以上兩種方案的構造函數和公用方法都是靜態的(static),則這個類實例是共享的。只是餓漢式在類加載的時候已經創建了對象,每次調用的時候不用再創建而是直接返回已經創建好的實例。這樣節省了時間,但卻占用了空間,實例本身為static的會一直駐留內存。

懶漢式在類加載時不創建對象,而是在程序使用到這個類的對象時才創建一次,以后每次使用該實例對象,則是判斷是否存在,若存在就加載,不存在就創建,這勢必會影響程序運行的速度。最關鍵的是,在並發的情況下,懶漢式是不安全的如果兩個線程線程1和線程2,在同一時間調用getInstance()方法,如果線程1先進入if語句剛剛判斷沒有該對象,准備創建對象時線程發生了切換,然后線程2進行控制判斷if語句沒有對象也會創建,那么就會有兩個實例被創建,所以懶漢式單例模式的getInstance()方法要加上同步控制符synchronized,以保證並發訪問的安全性。



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com