热门问题
时间线
聊天
视角

單例模式

一種設計模式 来自维基百科,自由的百科全书

单例模式
Remove ads

面向對象編程中,單例模式(英語:singleton pattern),是一種常用的創建型軟件設計模式[1]。在應用這個模式時,單例對象的必須保證只有一個實例存在。許多時候整個系統只需要擁有一個的全局對象,這樣有利於我們協調系統整體的行為。比如在某個服務器程序中,該服務器的配置信息存放在一個文件中,這些配置數據由一個單例對象統一讀取,然後服務進程中的其他對象再通過這個單例對象獲取這些配置信息。這種方式簡化了在複雜環境下的配置管理。

Thumb
單例模式的UML類別圖

實現

實現單例模式的思路是:一個類能返回對象一個引用(永遠是同一個)和一個獲得該實例的方法(必須是靜態方法,通常使用getInstance這個名稱);當我們調用這個方法時,如果類持有的引用不為空就返回這個引用,如果類保持的引用為空就創建該類的實例並將實例的引用賦予該類保持的引用;同時我們還將該類的構造函數定義為私有方法,這樣其他處的代碼就無法通過調用該類的構造函數來實例化該類的對象,只有通過該類提供的靜態方法來得到該類的唯一實例。

單例模式在多線程的應用場合下必須小心使用。如果當唯一實例尚未創建時,有兩個線程同時調用創建方法,那麼它們同時沒有檢測到唯一實例的存在,從而同時各自創建了一個實例,這樣就有兩個實例被構造出來,從而違反了單例模式中實例唯一的原則。 解決這個問題的辦法是為指示類是否已經實例化的變量提供一個互斥鎖(雖然這樣會降低效率)。

通常單例模式在Java語言中,有兩種構建方式:

  • 懶漢方式。指全局的單例實例在第一次被使用時構建。
  • 餓漢方式。指全局的單例實例在類裝載時構建。
Remove ads

例子

C++

設計模式》書中早於C++98的例子的C++23實現:

import std;

class Singleton {
private:
    Singleton() = default; // no public constructor
    ~Singleton() = default; // no public destructor
    inline static Singleton* instance = nullptr; // declaration class variable
    int value;
public:
    // defines a class operation that lets clients access its unique instance.
    static Singleton& getInstance() {
        if (!instance) {
            instance = new Singleton();
        }
        return instance;
    }
  
    Singleton(const Singleton&) = delete("Copy construction disabled");
    Singleton& operator=(const Singleton&) = delete("Copy assignment disabled");

    static void destroy() {
        delete instance;
        instance = nullptr;
    }

    // existing interface goes here
    [[nodiscard]]
    int getValue() const noexcept {
        return value;
    }

    void setValue(int newValue) noexcept {
        value = newValue;
    }
};

int main() {
    Singleton::getInstance().setValue(42);
    std::println("value = {}", Singleton::getInstance().getValue());
    Singleton::destroy();
}

程序輸入為:

value=42

下面是Meyers所著書中單例模式的C++11實現[2]。Meyers單例模式沒有毀壞(destruct)方法。這個程序的輸出同於上例。

import std;

class Singleton {
private:
    Singleton() = default;
    ~Singleton() = default;
    int value;
public:
    static Singleton& getInstance() {
        static Singleton instance;
        return instance;
    }
  
    [[nodiscard]]
    int getValue() const noexcept {
        return value;
    }
  
    void setValue(int newValue) noexcept {
        value = newValue;
    }
};

int main() {
    Singleton::getInstance().setValue(42);
    std::println("value = {}", Singleton::getInstance().getValue());
}

Java

Java中語言,單例模式(餓漢模式)應用的例子如下述代碼所示:

public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
  
    // Private constructor suppresses
    // default public constructor
    private Singleton() {};
 
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

Java編程語言中,單例模式(懶漢模式)應用的例子如下述代碼所示 (此種方法只能用在JDK5及以後版本(注意 INSTANCE 被聲明為 volatile),之前的版本使用「雙重檢查鎖」會發生非預期行為[3]):

public class Singleton {
    private static volatile Singleton INSTANCE = null;
  
    // Private constructor suppresses 
    // default public constructor
    private Singleton() {};
  
    //Thread safe and performance  promote 
    public static  Singleton getInstance() {
        if(INSTANCE == null) {
            synchronized(Singleton.class) {
                // When more than two threads run into the first null check same time, 
                // to avoid instanced more than one time, it needs to be checked again.
                if(INSTANCE == null) { 
                    INSTANCE = new Singleton();
                }
            } 
        }
        return INSTANCE;
    }
}
Remove ads

Python

Python的例子:

class Singleton():
    __instance = None
    def __new__(cls, *args, **kwargs):
        if cls.__instance is None:
            obj = super().__new__(cls)
            cls.__instance = obj
            obj.__initialize(*args, **kwargs)
        else:
            obj = cls.__instance
        return obj
    def __initialize(self, *args, **kwargs):
        for key, value in kwargs.items():
            self.__dict__[key] = value
Remove ads

參考文獻

外部連結

參見

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads