什么是設(shè)計模式: 被反復使用,代碼設(shè)計經(jīng)驗的總結(jié)
使用設(shè)計模式目的: 代碼的重用拣挪,讓代碼更易于理解擦酌,保證代碼可靠性
概念
- 單例對象的類必須保證只有一個實例存在。
適合場景
- 整個系統(tǒng)只需要擁有一個的全局對象菠劝。
分類
- 懶漢式:指全局的單例實例在第一次被使用時構(gòu)建
- 餓漢式:指全局的單例實例在類裝載時構(gòu)建
- 靜態(tài)內(nèi)部類: 在靜態(tài)內(nèi)部類中聲明一個instance
步驟
- 構(gòu)造器私有化
- 創(chuàng)建類的唯一實例赊舶,使用private static 修飾
- 提供一個獲取實例的public方法
- enum枚舉
餓漢式(線程安全)
class Singleton{
//類加載時創(chuàng)建instance
private static Singleton instance = new Singleton();
private Singleton(){
}
public Singleton getInstance(){
return instance;
}
}
懶漢式
class Singleton{
//僅僅聲明instance
private static Singleton instance ;
private Singleton(){
}
public Singleton getInstance(){
if(instance==null){
instance = new Singleton();
}
return instance;
}
}
上面這種getInstance有致命的缺陷,就是無法保證線程安全赶诊。而給整個方法加synchronized效率不高笼平。考慮到同步操作只需要在第一次調(diào)用時才被需要舔痪,即第一次創(chuàng)建單例實例對象時寓调。這就引出了雙重檢驗鎖。
雙重檢驗鎖
是一種使用同步塊加鎖的方法锄码。程序員稱其為雙重檢查鎖夺英,因為會有兩次檢查 instance == null,一次是在同步塊外滋捶,一次是在同步塊內(nèi)痛悯。為什么在同步塊內(nèi)還要再檢驗一次?因為可能會有多個線程一起進入同步塊外的 if重窟,如果在同步塊內(nèi)不進行二次檢驗的話就會生成多個實例了载萌。
public Singleton getInstance(){
if(instance==null){
synchronized(Singleton.class){
if(instance==null)
instance = new Singleton();
}
}
return instance;
}
靜態(tài)內(nèi)部類
class Singleton{
private static class SingletonHolder{//使用私有修飾符
private static final Singleton instance = new Singleton();
}
private Singleton(){}
public static final Singleton getInstance(){
return SingletonHolder.instance;
}
}
這種寫法仍然使用JVM本身機制保證了線程安全問題;由于 SingletonHolder 是私有的亲族,除了 getInstance() 之外沒有辦法訪問它炒考,因此它是懶漢式的可缚;同時讀取實例的時候不會進行同步霎迫,沒有性能缺陷;也不依賴 JDK 版本帘靡。
枚舉
enum Dog {
DogA(1, "dog1"),DogB(2,"dog2");//實例
int age;//私有變量
String name;
Dog(int age, String name) {//構(gòu)造方法
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Dog{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
//調(diào)用
public static void main(String[] args) {
Dog dog = Dog.DogA;
System.out.println(dog);
}
總結(jié)
- 4種方式推薦使用后兩種知给,其中枚舉最適合,同時也最難理解描姚。