先看一個程序:
class Singleton { // 定義一個類
public void print() {
System.out.println("Hello World");
}
}
public class Test {
public static void main(String args[]) {
Singleton inst = null; // 聲明對象
inst = new Singleton(); // 實例化對象
inst.print(); // 調用方法
}
}
上面的Singleton類裏是存在構造方法的(如果一個類中沒有明確的定義一個構造方法的話,會自動生成一個無參默認的構造方法),現在把構造方法修改一下:
class Singleton { // 定義一個類
private Singleton() {
} // 構造方法私有化
public void print() {
System.out.println("Hello World");
}
}
我們知道,構造方法被私有化,就無法在類外部實例化Singleton對象。
那麼,此時,如何在Test類裏面得到Singleton類的實例化對象並且調用print()方法?
首先,這個類的構造方法被私有化,只能被本類所調用,所以可以在本類中產生本類的實例化對象:
class Singleton { // 定義一個類
Singleton instance = new Singleton();//在本類中產生本類的實例化對象
private Singleton() {
} // 構造方法私有化
public void print() {
System.out.println("Hello World ");
}
}
我們知道,此時instance 屬性只是一個普通屬性,必須在類實例化對象後再可以使用,要想不需要實例化對象直接使用,可以使用static聲明:
class Singleton { // 定義一個類
static Singleton instance = new Singleton();
private Singleton() {
} // 構造方法私有化
public void print() {
System.out.println("Hello World");
}
}
public class Test {
public static void main(String args[]) {
Singleton inst = null; // 聲明對象
inst = Singleton.instance; // 實例化對象
inst.print(); // 調用方法
}
}
但是,我們知道,類中的全部屬性都應該封裝,以上的instance屬性也應該封裝:
private static Singleton instance = new Singleton();
而封裝之後要想取得屬性。要編寫getter方法,不過這裏的getter方法應該也由類名稱直接調用,定義爲static型,getInstance()方法:
class Singleton { // 定義一個類
private static Singleton instance = new Singleton();
private Singleton() {
} // 構造方法私有化
public void print() {
System.out.println("Hello World ");
}
public static Singleton getInstance() {
return instance;
}
}
public class Test {
public static void main(String args[]) {
Singleton inst = null; // 聲明對象
inst = Singleton.getInstance(); // 實例化對象
inst.print(); // 調用方法
}
}
爲什麼這麼做呢?此時程序之中的instance屬性,屬於static,那麼,不管有多少個Singleton類的對象,都共同擁有同一個instance屬性。
我們再來看,若getInstance()方法修改如下:
public static Singleton getInstance() {
instance = new Singleton();
return instance;
}
此時,發現,每調用一次getInstance()方法,就會實例化一個Singleton對象,這樣的話,實例化對象就不是唯一的了,所以,這種情況不能讓它出現,怎麼辦?可以在定義instance屬性的時候增加一個final關鍵字:
private static final Singleton INSTANCE = new Singleton() ;
於是,最後的代碼就變成了這樣:
class Singleton { // 定義一個類
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
} // 構造方法私有化
public void print() {
System.out.println("Hello World .");
}
public static Singleton getInstance() {
return INSTANCE;
}
}
public class Test {
public static void main(String args[]) {
Singleton inst = null; // 聲明對象
inst = Singleton.getInstance(); // 實例化對象
inst.print(); // 調用方法
}
}
這樣的設計在設計模式上講就稱爲單例設計模式(Singleton)。
單例設計模式的類型:
(1)餓漢式單例模式:當類裝載的時候就會創建類的實例,不管你用不用,先創建出來,然後每次調用的時候,就不需要再判斷。上面的程序就屬於餓漢式單例模式,
(2)懶漢式單例類:每次獲取實例都會進行判斷,看是否需要創建實例,如果一直沒有人使用的話,那就不會創建實例。代碼如下:
class Singleton { // 定義一個類
private static Singleton instance;
private Singleton() {
} // 構造方法私有化
public void print() {
System.out.println("Hello World .");
}
public static Singleton getInstance() {
if (instance == null) { // 沒有實例化
instance = new Singleton(); // 實例化
}
return instance;
}
}
小結:單例模式的特點?
(1)構造方法被私有化(private);
(2)只能夠通過getInstance()方法取得Singleton類的實例化對象,這樣不管外部如何操作,最終也只有一個實例化對象;
(3)在單例設計模式之中,一定會存在一個static方法,用於取得本類的實例化對象。