單例模式
1. 單例模式
1.1 要求
當前類有且只有一個對象,一旦當前類存在一個對象之後,無法在重新創建當前類的對象。就算是你要創建,代碼返回的對象依然是上一次創建的對象。
懶漢模式,餓漢模式
1.2 單例模式推導【懶漢】
package com.qfedu.a_single;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* SingleDog要求是一個單例類,整個代碼運行週期內有且只有一個類對象
*
* 不可取方式:
* @全體成員 SingleDog類使用一個單例類,我創建過對象了,你們不要搞事情
* 紅包
* 【期望】
* 從語法角度約束一些行爲。
* 目前創建對象過於簡單,new + 構成方法組合非常easy
* 【解決方案】
* private修飾構造方法
*
* 【問題】
* 構造方法私有化之後,類外沒有操作構造方法的權限,沒辦法創建對象
* 【解決方案】
* 1. 暴力反射
* 暴力反射,給予構造方法操作權限,這裏和沒有使用private有什麼區別
* 【不合適】
* 2. 期望
* 類外最起碼有一個對象。
* a. 類外沒有SingleDog類對象
* b. 期望獲取到一個SingleDog對象
*
* 需要方法來完成
* 1. 該方法要求靜態成員方法,沒有對象,需要通過類名調用
* 2. 類外要求使用public修飾
* 3. 該方法需要得到一個SingleDog對象,返回值類型是SingleDog
* 4. 方法參數爲無參數,構造方法也是無參
* 5. 方法名 getInstance
* public static SingleDog getInstance()
*
* 【問題】
* 依然是不同對象
*
* 【期望】
* 1. 調用該方法每一次調用都是new新的對象。
* 2. 這個new得有限制,如果之前創建過對象,你就不能再new了,沒有對象可以new
* 3. 存在一個變量可以保存之前創建對象的空間首地址,並且可以持久性保存。
* 分析:
* a. 需要保存SingleDog類對象空間首地址
* SingleDog類型
* b. 該數據不能類外輕鬆獲取
* private
* c.
* (1) 靜態方法可以使用
* (2) 有一定的持久性
* static修飾成員變量
* private static SingleDog sd = null;
* 【getInstance方法】
* 需要判斷
* 判斷SingleDog類型的靜態成員變量 sd是否保存有之前創建的空間首地址
*
* 【問題】
* 多線程情況下,存在線程搶佔問題,極有可能導致當前方法被兩個線程同時執行,同時
* 創建對象
* com.qfedu.a_single.SingleDog@22673956
* com.qfedu.a_single.SingleDog@6223c513
*
* 【期望】
* 在多線程情況下,也是安全的
* 【解決方案】
* 加鎖
* 【牆裂推薦】synchronized同步代碼塊
* 使用同步代碼塊,用什麼做鎖對象?
* 最合適的鎖對象依然是Single.class
*
* 【牆裂推薦】synchronized同步方法
* static修飾靜態方法的情況下,什麼是鎖對象?
* 當前SingleDog類.class字節碼文件
*
* 【不推薦】Lock鎖對象
* 和以上兩個方式對比?
* new ==> lock ==> 多出一個Lock鎖空間
* (1) 在getInstance方法new lock是不合適,多個線程情況下
* 可能會出現不同鎖情況
* (2) Lock做成靜態成員變量
* 浪費空間了!!!
*
*
* @author Anonymous 2020/3/13 10:53
*/
public class SingleDog {
private static SingleDog sd = null;
private SingleDog() {}
// 同步方法
public static synchronized SingleDog getInstance() {
if (null == sd) {
sd = new SingleDog();
}
return sd;
}
}
public class SingleDog1 {
private static SingleDog1 sd = null;
private SingleDog1() {}
// 同步代碼塊
public static SingleDog1 getInstance() {
synchronized (SingleDog1.class) {
if (null == sd) {
sd = new SingleDog1();
}
}
return sd;
}
}
1.3 另一種單例模式【餓漢】
package com.qfedu.a_single;
/**
* 另一個單例模式
*
* @author Anonymous 2020/3/13 11:44
*/
public class SingleCat {
/*
static修飾,在代碼的加載階段創建完成
並且使用final修飾,保存當前指向不可以改變
private修飾類外無法直接獲取,不能修改
*/
private static final SingleCat sc = new SingleCat();
private SingleCat() {}
/*
使用方法做的統一
*/
public static SingleCat getInstance() {
return sc;
}
}