原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。http://haolloyin.blog.51cto.com/1177454/332469
單例模式(Singleton):當系統中只需要的某個類的唯一對象時,可以使用該模式。
爲什麼會用到該模式?因爲有時候某些對象的創建需要耗費大量的資源、使用單一(唯一)的對象實例來維護某些共享數據等,在這些場景下即可採用單例模式進行設計,可以適當地漸少內存開銷,因爲此時該唯一對象不會(被限制了)頻繁地創建。
一個簡單單例類圖如下:
代碼實現如下:
單例類Singleton01:
class Singleton01 {
private static Singleton01 singleton = null;
// 私有的構造函數,限制外部環境的非法創建和訪問
private Singleton01() {
//一些初始化操作
}
// 靜態方法,用於創建單例類的“唯一”實例
public static Singleton01 getInstance() {
if (singleton == null) {
singleton = new Singleton01();
}
return singleton;
}
// 單例類也需要提供其他靜態方法給外部環境訪問,完成一定的服務
public void doSomethings() {
System.out.println("do somethings ...");
}
}
客戶端類Client:
public class Client {
public static void main(String[] args) {
Singleton01 s1 = Singleton01.getInstance();
Singleton01 s2 = Singleton01.getInstance();
Singleton01 s3 = Singleton01.getInstance();
System.out.println("s1 == s2 : " + (s1 == s2));
System.out.println("s1 == s3 : " + (s1 == s3));
System.out.println("s2 == s3 : " + (s2 == s3));
}
}
注意:如此設計的單例類並不是線程安全的,原因大家都明白,在getInstance()方法中的條件判斷並不是原子性的,當多個線程同時訪問時則可能出現混亂,所以我們可以在該方法前加上synchronized關鍵字來保證其被同步訪問。但是,學過OS進程同步知識的我們知道,此時的同步還不是很嚴格的,我記得是需要兩個條件判斷來實現的,具體的優化實現請參考具體的教材。
其實,如果真正地只想某個類僅僅擁有一個唯一的實例,使用下面這種“餓漢式”的實現更加合理些,請詳看其中的不同之處。
“餓漢式”Singleton02類:
class Singleton02 {
// 直接爲該單例類創建一個實例對象
private final static Singleton02 singleton = new Singleton02();
private Singleton02() {
//一些初始化操作
}
// 直接返回唯一的單例對象
public static Singleton02 getInstance() {
return singleton;
}
public void doSomethings() {
System.out.println("do somethings ...");
}
}
另外,有時我們並不僅僅滿足於一個唯一的實例對象,而是需要爲數不多但是又不能超過一定數量的實例對象,此時可以用一個容器來預先創建並裝載一定數量的實例,在提供一個外部接口供外部訪問獲得其中一個實例。
此時的類圖如下:
代碼實現如下:
Singleton03類:
class Singleton03 {
private final static int MAX_NUM_OF_INSTANCE = 3;
private static List<Singleton03> singletonList = new ArrayList<Singleton03>();
//以靜態代碼塊的方式來初始化一定數量的單例對象
static {
for(int i = 0; i < MAX_NUM_OF_INSTANCE; i++) {
singletonList.add(new Singleton03());
}
}
public static Singleton03 getInstance() {
//從單例類已持有的實例中隨機取出一個實例
Random random = new Random();
int id = random.nextInt(MAX_NUM_OF_INSTANCE);
return singletonList.get(id);
}
private Singleton03() {
//一些初始化操作
}
public void doSomethings() {
System.out.println("do somethings ...");
}
}
以上是我學習參考了秦小波的《設計模式之禪》中的單例模式以及其他之前看過的相關書籍之後,結合自己的理解和總結得出的,希望以此來鞏固學過的知識,更希望能與正在學習中的大家互相學習共同進步!
本文出自 “螞蟻” 博客,請務必保留此出處http://haolloyin.blog.51cto.com/1177454/332469