單例模式
單例模式(singleton): 保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
單例模式個人感覺是最簡單的設計模式,因爲他的目的很簡單,並且沒有用到太多的面對對象的特徵,所以很簡單。
單例模式主要是爲了不要有重複的實例出現。
主要分爲了兩種:
懶漢
public class Singleton {
private static Singleton instance;
private Singleton() {} ;
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
Singleton通過將構造方法限定爲private避免了類在外部被實例化,在同一個虛擬機範圍內,Singleton的唯一實例只能通過getInstance()方法訪問。 當時當多線程的時候難免會出現多個實例,所以線程不安全。
惡漢
public class Singleton {
private static fianl Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
惡漢在類創建的時候就已經實例化好一個靜態的實例,而且不會被改變了,所以它天生就是線程安全。
針對懶漢的線程不安全的問題又出現了集中安全的懶漢:
- 在getInstance()方法上加鎖
public class Singleton {
private static Singleton instance;
private Singleton() {} ;
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
這種辦法雖然成功的解決了線程問題,但是在方法上加鎖每次都要都要同步,浪費很多性能。
- 雙重檢查鎖定
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
同樣的既然加鎖就會同步,只不過比上面那種稍好一點因爲鎖的內容越少,消耗越小。
- 靜態內部類
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
這種方法和餓漢很相似,只不過不同的是,使用了內部類,所以在類創建的時候並不會創建實例,而是在調用的時候創建實例,這種方法算是融合懶漢和餓漢的有點,同時也不會有加鎖的問題。
其實還有更好的就是使用1.5後更新的新特性,就是使用枚舉,這種方式也是最提倡的。
public enum Singleton {
INSTANCE;
}
簡單粗暴
至此五種創建型的設計模式已經全部學習完畢
分別是:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
下次將學習結構型設計模式。