設計模式 - 單例模式 (Creational Patterns - Singleton Pattern)

前言

單例模式處處可見,而我個人目前使用單例模式的時機是,當今天確定此物件只需有一個時就使用single pattern。但是在某天有幸看到一篇文章評論Singleton濫用情形,開始思考單一Class的必要性。

單例模式特性

  • 確保整個Application只會有此一個物件
  • 為了確保整個Application只會有此物件,所以會需要static關鍵字,這也代表著會變成全域物件

單例模式會讓物件變成全域物件,這也是許多神人對與單例模式濫用批評的原因,會開放其實沒有必要變成全域的物件被接觸到

使用時機

當此物件是全域的,而且容易連續被使用以及需要強調單一則可以考慮使用。

  • Logger
  • Configuration
  • Cache

範例

Singleton分為兩種實踐方式,Lazy/Early懶漢與餓漢,實作Singleton最重要的是,多執行續時Singleton會不會有重複創建的問題,所以在Lazy實做時就會使用到最基本的Java Lock (synchronized),而Early使用到Final前綴字。

懶漢與餓漢差別
在於物件的初始化實機,懶就是晚一點餓就是一開始就來。

LazySingleton.java

public class LazySingleton {
    private static volatile LazySingleton instance;

    private LazySingleton() {}

    public static LazySingleton getInstance(String value) {
        if (instance == null) {
            synchronized (LazySingleton.class) {
                if (instance == null) {
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }
}

LazySingleton.java

public class EarlySingleton {
    private EarlySingleton() {}

    private static class EarlySingletonHolder {
        private static final EarlySingleton INSTANCE = new EarlySingleton();
    }

    public static EarlySingleton getInstance() {
        return EarlySingletonHolder.INSTANCE;
    }
}

原始碼請點我

結論

如果想創建一個,常常被全域使用,而且重複創造物件是種很浪費的行為時可以考慮使用Singleton,若是在Java初始化時對於物件佔用空間影響覺得還好時,可以考慮使用餓漢;相反的則使用懶漢,當物件被第一次呼叫時在創建。

留言

這個網誌中的熱門文章

Java Lambda Map篇

(InterviewBit) System Design - Design Cache System

設計模式 - 享元模式 (Structural Patterns - Flyweight Design Pattern)