設計模式一--單例設計模式 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 一、定義 Singleton Pattern: 確保一個類只有一個實例,並且自行實例化並向整個系統提供這個實例。 二、分類 餓漢式單例類:類載入時就進行對象的實例化 懶漢式單例類:第一次引用類時,才進行對象的實例化。 ...
設計模式一--單例設計模式
版權聲明:本文為博主原創文章,未經博主允許不得轉載。
一、定義
Singleton Pattern:
確保一個類只有一個實例,並且自行實例化並向整個系統提供這個實例。
二、分類
餓漢式單例類:類載入時就進行對象的實例化
懶漢式單例類:第一次引用類時,才進行對象的實例化。
三、核心代碼
3.1 餓漢式
class Singleton{ private static Singleton m_instance=new Singleton(); //構造方法私有,保證外界無法直接實例化 private Singleton(){ } //通過該方法獲得實例對象 public static Singleton getInstances(){ return m_instance; } }
3.2 懶漢式
class Singleton2{ private static Singleton2 _instance=null; //構造方法私有,保證外界無法直接實例化 private Singleton2(){ } //通過該方法獲得實例對象 public static Singleton2 getInstances(){ if(_instance==null){ _instance=new Singleton2(); } return _instance; } }
四、實例
4.1 餓漢式
class Singleton{ //成員變數x用來測試 int x; private static Singleton m_instance=new Singleton(); //構造方法私有,保證外界無法直接實例化 private Singleton(){ } //通過該方法獲得實例對象 public static Singleton getInstances(){ return m_instance; } } public class SingletonPattern { public static void main(String[] args) { Singleton.getInstances(); Singleton.getInstances().x=1; } }
4.2 懶漢式
class Singleton2{ //成員變數x用來測試 int x; private static Singleton2 _instance=null; //構造方法私有,保證外界無法直接實例化 private Singleton2(){ } //通過該方法獲得實例對象 public static Singleton2 getInstances(){ if(_instance==null){ _instance=new Singleton2(); } return _instance; } } public class SingletonPattern2 { public static void main(String[] args) { Singleton2.getInstances(); Singleton2.getInstances().x=1; System.out.println(Singleton2.getInstances().x=1); } }
五、單例模式的優缺點
5.1 優點
只有一個實例,減少記憶體開銷,避免對資源的多重占用
可以設置全局訪問點,優化和共用資源訪問
5.2 缺點
無法創建子類
單例模式與單一職責原則有衝突
六、單例模式的使用場景
要求生成唯一序列號的地方
在整個項目中需要一個共用訪問點和共用數據
創建一個對象消耗的資源太多
需要定義大量的靜態常量和靜態方法(如工具類)的環境
七、單例模式的應用實例
7.1 代碼
1 class GlobalNum{ 2 3 private int num=0; 4 5 private static GlobalNum globalNum=new GlobalNum(); 6 7 // 8 9 public static GlobalNum getInstance() { 10 11 return globalNum; 12 13 } 14 15 //synchronized同步化 16 17 public synchronized int getNum() { 18 19 return num++; 20 21 } 22 23 public synchronized void setNum(int num) { 24 25 this.num = num; 26 27 } 28 29 } 30 31 32 33 class NumbelThread extends Thread{ 34 35 private String threadName; 36 37 public NumbelThread(String name) { 38 39 threadName=name; 40 41 } 42 43 44 45 public void run(){ 46 47 GlobalNum globalNum=GlobalNum.getInstance(); 48 49 //迴圈訪問,輸出訪問次數 50 51 for (int i = 0; i < 5; i++) { 52 53 System.out.println(threadName+"第"+globalNum.getNum()+"次訪問"); 54 55 56 57 } 58 59 } 60 61 } 62 63 64 65 public class SingletonDemo { 66 67 68 69 public static void main(String[] args) { 70 71 NumbelThread threadA=new NumbelThread("線程A"); 72 73 NumbelThread threadB=new NumbelThread("線程B"); 74 75 threadA.start(); 76 77 threadB.start(); 78 79 } 80 81 82 83 }
7.2 運行結果
線程A第0次訪問
線程B第1次訪問
線程A第2次訪問
線程A第4次訪問
線程B第3次訪問
線程B第6次訪問
線程B第7次訪問
線程A第5次訪問
線程B第8次訪問
線程A第9次訪問