JAVA基礎 單例模式
技術標籤:JAVA基礎第一階段java設計模式
單例模式
什麼是單例模式Singleton?
Singleton:在JAVA中指單例設計模式,它是軟體開發中最常用的設計模式之一。
這種模式涉及到一個單一的類,該類負責建立自己的物件,同時確保只有單個物件被建立。這個類提供了一種訪問其唯一的物件的方式,可以直接訪問,不需要例項化該類的物件。
單:唯一
例:例項
基礎知識:
類: 是指描述一種事物的定義,是個抽象的概念
例項:指實際存在的例子,事物的一個具體的個體,或是具體的東西。
比如說:“人”是一個類。“張三”是人類的一個具體例子,就是例項化。
在程式設計時也是同樣的道理,你先自己定義一個“類”,當你需要用時,用“類”的定義來創造一個具體的例子。用類的定義來建立一個例項,就叫做類的例項化。
單例設計模式,即某一個類在整個系統中只能有一個例項物件可以被獲取和使用的程式碼模式
注意:
1、單例類只能有一個例項。
怎麼呼叫呢?構造器私有化
2、單例類必須自己建立自己的唯一例項。
含有一個改類的靜態變數來儲存這個唯一的例項
3、單例類必須給所有其他物件提供這一例項。
對外提供獲取該例項物件的方式:
(1)直接暴露出來
(2)用靜態變數get方法來獲取
例項:
1、一個班級只有一個班主任。
2、Windows是多程序多執行緒的,在操作一個檔案的時候,就不可避免地出現多個程序或執行緒同時操作一個檔案的現象,所以所有檔案的處理必須通過唯一的例項來進行。3、一些裝置管理器常常設計為單例模式,比如一個電腦有兩臺印表機,在輸出的時候就要處理不能兩臺印表機列印同一個檔案。
優點:
1、在記憶體裡只有一個例項,減少了記憶體的開銷,尤其是頻繁的建立和銷燬例項(比如管理學院首頁頁面快取)。
2、避免對資源的多重佔用(比如寫檔案操作)。
缺點:
沒有介面,不能繼承,與單一職責原則衝突,一個類應該只關心內部邏輯,而不關心外面怎麼樣來例項化。
幾種常見形式:
餓漢式∶直接建立物件,不存線上程安全問題
-直接例項化餓漢式(簡潔直觀)
-列舉式(最簡潔)
-靜態程式碼塊餓漢式(適合複雜例項化)
懶漢式:延遲建立物件
-執行緒不安全(適用於單執行緒)
-靜態內部類形式(適用於多執行緒)
餓漢式:
package com.tedu.single;
/**
* 餓漢式:
* 直接建立例項物件,不管你是否需要這個物件,都會建立
*
* 1.構造器私有化 private
* 2.自行建立,並且靜態變數儲存 static
* 3.向外提供這個例項 public
* 4.強調這是一個單例,我們可以final修飾
*
* 常量我們習慣性的寫為大寫 INSTANCE
*/
public class Singleton1 {
public static final Singleton1 INSTANCE = new Singleton1();
private Singleton1(){
}
}
獲取方式測試:
package com.tedu.test;
import com.tedu.single.Singleton1;
public class TestSingleton1 {
public static void main(String[] args) {
Singleton1 s = Singleton1.INSTANCE;
System.out.println(s);
}
}
執行結果:
列舉:
package com.tedu.single;
/**
* 列舉型別:表示該型別的物件是有限的幾個
* 我們可以限定為一個,就成了單例
*/
public enum Singleton2 {
INSTANCE;
}
獲取方式測試:
package com.tedu.test;
import com.tedu.single.Singleton2;
public class TestSingleton1 {
public static void main(String[] args) {
Singleton2 s = Singleton2.INSTANCE;
System.out.println(s);
}
}
執行結果:
我們可以發現著兩種模式好像沒什麼區別,基本上一樣,JDK1.5之前與JDK1.5之後的分別。
靜態程式碼塊:
package com.tedu.single;
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiNilLoader;
import java.io.IOException;
import java.util.Properties;
//靜態程式碼塊
public class Singleton3 {
public static final Singleton3 INSTANCE;
//什麼時候可能會用到這種方法呢?屬性需要初始化
private String info;
static {
try {
Properties pro=new Properties();
pro.load(Singleton3.class.getClassLoader().getResourceAsStream("single.properties"));
INSTANCE = new Singleton3(pro.getProperty("info"));
} catch (IOException e) {
e.printStackTrace();
}
}
private Singleton3(String info){
this.info=info;
}
public static Singleton3 getINSTANCE() {
return INSTANCE;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
以上就是餓漢式的三種寫法
懶漢式:
package com.tedu.test;
import com.tedu.single.Singleton4;
public class TsetSingleton4 {
public static void main(String[] args) {
Singleton4 s1= Singleton4.getInstance();
Singleton4 s2= Singleton4.getInstance();
System.out.println(s1==s2);
System.out.println(s1);
System.out.println(s2);
}
}
測試:
package com.tedu.test;
import com.tedu.single.Singleton4;
public class TsetSingleton4 {
public static void main(String[] args) {
Singleton4 s1= Singleton4.getInstance();
Singleton4 s2= Singleton4.getInstance();
System.out.println(s1==s2);
System.out.println(s1);
System.out.println(s2);
}
}
執行結果: