《伊甸之路》續作《伊甸決鬥者》上架Steam 2022年發售
阿新 • • 發佈:2022-02-08
介紹
單例(Singleton Pattern)是設計模式中最簡單的一種。屬於建立型模式
。它提供了一種建立物件的最佳方式,即記憶體中只有一個例項。也就是不會有人使用 new Singleton()
來生成一個新的物件。
意圖
保證一個類僅有一個例項,並提供一個訪問它的全域性方法。
解決
一個全域性使用的類頻繁的建立與銷燬。
優點
-
記憶體中只有 一個例項,減少了記憶體開銷,避免了頻繁的建立及銷燬例項;
-
避免對資源的多重佔用(寫檔案操作);
缺點
沒有介面,不能繼承,與單一原則衝突,一個類應該只關心內部邏輯,而不關係外部怎樣例項化。
使用場景
-
系統產生唯一序列號;
-
WEB中的計數器,不用每次重新整理在資料庫中加一次,使用單例先快取起來;
UML
示例
-
最常用的一種,也是最簡單的一種
餓漢模式:(推薦)
/* * 功能描述: * 〈餓漢式單例模式 * 類載入到記憶體後,就例項化一個單例,JVM保證執行緒安全 * 簡單實用,推薦使用 * 缺點:不管用到與否,類裝載時完成例項化。 * 〉 * * @author : geoary * @date : 2019/12/10 21:33 */ public class Mgr01 { private static final Mgr01 INSTANCE = new Mgr01(); // 私有的建構函式 private Mgr01(){ } // 獲取唯一物件例項 public static Mgr01 getInstance(){ return INSTANCE; } public static void main(String[] args) { Mgr01 mgr01 = Mgr01.getInstance(); Mgr01 mgr02 = Mgr01.getInstance(); System.out.println(mgr01 == mgr02); } }
-
懶載入模式1:
/** * 功能描述: * 〈懶載入 * 雖然達到了按需初始化的目的,但是帶來了執行緒不安全問題 * 〉 * * @author : geoary * @date : 2019/12/10 21:53 */ public class Mgr03 { private static Mgr03 INSTANCE; private Mgr03() { } public static Mgr03 getInstance() { if (INSTANCE == null) { try { Thread.sleep(1); } catch (Exception e) { e.printStackTrace(); } INSTANCE = new Mgr03(); } return INSTANCE; } public static void main(String[] args) { for (int i = 0; i < 100; i++) { /*new Thread(new Runnable() { @Override public void run() { System.out.println(Mgr03.getInstance().hashCode()); } }).start();*/ new Thread(() -> System.out.println(Mgr03.getInstance().hashCode())).start(); } } }
-
懶載入模式2:
/** * 功能描述: * 〈懶載入 * 通過 synchronized 解決執行緒問題,但是效率下降 * 〉 * * @author : geoary * @date : 2019/12/10 21:59 */ public class Mgr04 { private static Mgr04 INSTANCE; private Mgr04(){ } public static synchronized Mgr04 getInstance(){ if (INSTANCE == null){ try { Thread.sleep(1); }catch (Exception e){ e.printStackTrace(); } INSTANCE = new Mgr04(); } return INSTANCE; } public static void main(String[] args) { for (int i=0;i<100;i++){ new Thread(()-> System.out.println(Mgr04.getInstance().hashCode())).start(); } } }
-
靜態內部類
/** * 功能描述: * 〈靜態內部類 * jvm 保證單例 * 〉 * * @author : geoary * @date : 2019/12/10 22:12 */ public class Mgr07 { private Mgr07(){ } private static class Mgr07Holder{ private final static Mgr07 INSTANCE = new Mgr07(); } public static Mgr07 getInstance(){ return Mgr07Holder.INSTANCE; } public static void main(String[] args) { for (int i=0; i<100; i++){ new Thread(()-> System.out.println(Mgr07.getInstance().hashCode())).start(); } } }
以上提供了幾種實現單例模式的方式,其中最實用的是第一個
餓漢模式
,雖然會在類裝載的時候完成例項化,但是使用簡單而且執行緒安全。
應用場景demo
- 全域性序列生成器
Singleton.java
package cn.geoaryblog.design.cretedg.single;
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private int num = 0;
private String name = "預設姓名";
public static Singleton getInstance() {
return INSTANCE;
}
// 獲取序列
public static int getNextSeq(){
INSTANCE.num += 1;
return INSTANCE.num;
}
}
SingleMain.java
package cn.geoaryblog.design.cretedg.single;
public class SingleMain {
public static void main(String[] args) {
// 多個執行緒是否呼叫同一個例項
for (int i = 0; i < 20; i++) {
new Thread(() -> {
System.out.println("執行緒查詢到的序列是:" + Singleton.getNextSeq());
}).start();
}
}
}