版權宣告:本文為 Codeagles 原創文章,可以隨意轉載,但必須在明確位置註明出處!!!
###單例設計模式
- 什麼是單例設計模式? 所謂的單例設計指的是一個類只允許產生一個例項化物件。 我們來看單例設計模式是如何一步一步演化過來的。
####Talk is cheap, show me the code.
public class SingletonTest {
public static void main(String[] args) {
Singleton s= null;
s=new Singleton();
s.print();
}
}
class Singleton{
public Singleton(){}
public void print(){
System.out.println("Hello World");
}
}
複製程式碼
對於這段程式碼,很簡單都不陌生,就是建立Singleton類,然後在另一個類中去例項化物件呼叫print方法,最後輸出Hello World。原因是因為當我們在SingletonTest中例項化了物件的時候呼叫了Singleton類中的無參的構造方法,接下來結果就不足為奇了。
public class SingletonTest {
public static void main(String[] args) {
Singleton s= null;
s=new Singleton();//報錯
s.print();
}
}
class Singleton{
private Singleton(){}//私有構造方法
public void print(){
System.out.println("Hello World");
}
}
複製程式碼
那麼對於上述程式碼,進行改造,將構造方法的public改為private,那麼上述程式碼就會報錯,因為例項化的時候,構造方法被私有,表示該類不能被外部進行例項化物件,那麼如何解決這個問題,我們繼續看改造程式碼。
public class SingletonTest {
public static void main(String[] args) {
Singleton s= null;
s=Singleton.instance;//②
s.print();
}
}
class Singleton{
static Singleton instance = new Singleton();//①
private Singleton(){}//私有構造方法
public void print(){
System.out.println("Hello World");
}
}
複製程式碼
為了解決外部不能例項化物件的問題,那麼就在內部進行例項化物件,加上Singleton instance = new Singleton();
那麼就可以解決這個問題,但是在內部是解決了,外部依然無法呼叫print方法啊,因為外部沒有物件,所以我們想到用static關鍵字,例如①所示,然後在SingletonTest中如②直接類.物件
來建立新物件,再去呼叫print方法,問題搞定了。
那麼新的問題來了,以上雖然取得了Singleton類的例項化物件,但是對於類中的屬性應該用private
進行封裝,想要訪問封裝屬性知道需要提供getter
方法,那麼我們需要在①的前面加上private static Singleton instance = new Singleton();
不過此時訪問的是static
屬性,並且這個類無法在外部進行例項化物件建立,所以再提供一個static
方法,因為static
方法不受例項化控制。那麼改造的程式碼如下:
public class SingletonTest {
public static void main(String[] args) {
public static void main(String[] args) {
Singleton s= null;
s=Singleton.getInstance();//獲取例項化物件
//s1=Singleton.getInstance();//獲取例項化物件
//s2=Singleton.getInstance();//獲取例項化物件
s.print();
}
}
}
class Singleton{
private static Singleton instance = new Singleton();//加上private
//提供static方法,用來獲取例項化物件
public static Singleton getInstance(){
return instance;
}
private Singleton(){}//私有構造方法
public void print(){
System.out.println("Hello World");
}
}
複製程式碼
對於上述程式碼,在Singleton類中,提供了獲取例項化物件的靜態方法,也將屬性進行了私有化,那麼在SingletonTest中無論獲取多少個物件,實際上都是同一個物件,因為類載入的時候已經例項化了一次物件,這就是單例設計模式。
###擴充套件 對於單例設計模式,還有兩種型別:
- 餓漢式
- 懶漢式
####餓漢式 既然是餓漢式,我們就要在整體之中,只能有一個例項化物件,所以一般在原基礎上還會為其增加final關鍵字。這個沒有什麼分析的問題。
class Singleton{
private final static Singleton INSTANCE = new Singleton();//加上final
//提供static方法,用來獲取例項化物件
public static Singleton getInstance(){
return INSTANCE;
}
private Singleton(){}//私有構造方法
public void print(){
System.out.println("Hello World");
}
}
複製程式碼
對於程式碼改造就是一點,其他的都不變,這就是餓漢式。 ####懶漢式 所謂懶漢式,是指第一次去使用Singleton類物件的時候,才會為其進行例項化處理操作。
class Singleton{
private static Singleton instance;//不需要再去例項化
public static Singleton getInstance(){
if(instance==null){//表示此時還沒有例項化物件
instance=new Singleton();
}
return instance;
}
private Singleton(){}//私有構造方法
public void print(){
System.out.println("Hello World");
}
}
複製程式碼
這就是懶漢式,當然這個設計模式在後續多執行緒等部分會有效能問題,以後我們在進行討論。
對於單例的使用場景,比如windows中的回收站就是一個例子,不管是在C,D,E盤那個碟符中,都會有一個隱藏的回收站資料夾,將檔案放入到該資料夾後,再回到桌面上開啟回收站發現檔案在裡面,說明不論在哪,整個系統只有一個回收站,這就是典型的單例設計。
以上就是單例設計模式,一步一步在最基礎的程式碼中,演化出來的。