設計模式之——Singleton pattern
單例模式網址
單例模式定義
在一個系統中,一個類只有一個
例項化的物件。
單例模式應用
- The abstract factory, builder, and prototype patterns can use Singletons in their implementation.
- Facade objects are often singletons because only one Facade object is required.
- State objects are often singletons.
- Singletons are often preferred to global variables because:
- They do not pollute the global namespace (or, in languages with namespaces, their containing namespace) with unnecessary variables.<sup id="cite_ref-4" class="reference" style="line-height: 1; unicode-bidi: -webkit-isolate; white-space: nowrap; font-size: 12px; font-weight: normal; font-style: normal;">
- They permit lazy allocation and initialization, whereas global variables in many languages will always consume resources.
實現方案
The singleton pattern is implemented by creating a class with a method that creates a new instance of the class if one does not exist. If an instance already exists, it simply returns a reference to that object.
可以實現延遲載入
,即使用之前不佔用記憶體或資源。(Note the distinction between a simple static instance of a class and a singleton: although a singleton can be implemented as a static instance, it can also be lazily constructed, requiring no memory or resources until needed.)
The singleton pattern must be carefully constructed in multi-threaded applications. If two threads are to execute the creation method at the same time when a singleton does not yet exist, they both must check for an instance of the singleton and then only one should create the new one. If the programming language has concurrent processing capabilities the method should be constructed to execute as a mutually exclusive operation. The classic solution to this problem is to use mutual exclusion on the class that indicates that the object is being instantiated.
Lazy initialization
使用“雙重檢查加鎖”——double-checked locking
。其中變數 instance 是 volatile
的,1.4及更早的Java中,volatile關鍵字的實現會導致雙重檢查加鎖的失效。具體原因,參考 The "Double-Checked Locking is Broken" Declaration 。
public final class SingletonDemo {
private static volatile SingletonDemo instance;
private SingletonDemo() { }
public static SingletonDemo getInstance() {
if (instance == null ) {
synchronized (SingletonDemo.class) {
if (instance == null) {
instance = new SingletonDemo();
}
}
}
return instance;
}
}
在併發性並不是很高,效能並不特別需求的情況下,可以使用下面簡潔的方法:
public final class SingletonDemo {
private static SingletonDemo instance = null;
private SingletonDemo() { }
public static synchronized SingletonDemo getInstance() {
if (instance == null) {
instance = new SingletonDemo();
}
return instance;
}
}
Eager initialization
如果系統總是需要一個例項,或者建立例項的開銷並不大,可以使用Eager initialization,它總是返回一個例項。
public final class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
這種方法的好處:
- 在類載入之後、被任何執行緒使用之前,static 的變數 INSTANCE 就已經定義好。
- 方法
getInstance()
不需要同步,所有的執行緒都會看到同樣的例項。 - 關鍵字
final
使得 INSTANCE 不能修改,保證有且只有
一個例項。
Static block initialization
在static程式碼塊
中建立新例項,同Eager initialization
。
public final class Singleton {
private static final Singleton instance;
static {
try {
instance = new Singleton();
} catch (Exception e) {
throw new RuntimeException("Darn, an error occurred!", e);
}
}
public static Singleton getInstance() {
return instance;
}
private Singleton() {
// ...
}
}
Initialization-on-demand holder idiom
- 儘可能
延遲載入
- 適用於
所有
的 Java 版本 執行緒安全
public final class Singleton {
// Private constructor. Prevents instantiation from other classes.
private Singleton() { }
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
內部類SingletonHolder
在方法getInstance()
被呼叫時,才會被 class loader 載入。因此這個方法是執行緒安全的,不需要額外的同步手段。內部類SingletonHolder
也可以被定義成final的。
The enum way
In the second edition of his book Effective Java, Joshua Bloch claims that "a single-element enum type is the best way to implement a singleton" for any language that supports enums, like Java.
public enum Singleton {
INSTANCE;
public void execute (String arg) {
// Perform operation here
}
}
Java語言保證,列舉型別會在需要使用時,通過 class loader 載入。同時 Java 的列舉型別是全域性可見的,但是有些呆板 0_o。
相關文章
- 設計模式之單例模式(Singleton Pattern)設計模式單例
- Java設計模式之單例模式(Singleton Pattern)Java設計模式單例
- JAVA設計模式之 單例模式【Singleton Pattern】Java設計模式單例
- 設計模式--單例(Singleton Pattern)設計模式單例
- Java設計模式——單例模式(Singleton pattern)Java設計模式單例
- 常用設計模式-單例模式(Singleton pattern)設計模式單例
- PHP設計模式(一)—單例模式(Singleton Pattern)PHP設計模式單例
- 單態設計模式(Singleton Design Pattern)設計模式
- 設計模式系列之單例模式(Singleton Pattern)——確保物件的唯一性設計模式單例物件
- 單例模式(Singleton Pattern)單例模式
- 設計模式之代理模式(proxy pattern)設計模式
- 設計模式之單例模式 - Singleton設計模式單例
- 設計模式之Singleton - 單態模式設計模式
- 設計模式之策略模式和狀態模式(strategy pattern & state pattern)設計模式
- 設計模式之觀察者模式(Observer Pattern)設計模式Server
- 設計模式之狀態模式---State Pattern設計模式
- JAVA設計模式之 代理模式【Proxy Pattern】Java設計模式
- Java設計模式之單例模式(Singleton)Java設計模式單例
- 1/24 設計模式之策略設計模式 Strategy Pattern設計模式
- 建立型模式 --- 單件模式(Singleton Pattern)模式
- 我所理解的設計模式(C++實現)——單例模式(Singleton Pattern)設計模式C++單例
- 使用C# (.NET Core) 實現單體設計模式 (Singleton Pattern)C#設計模式
- 設計模式之裝飾器模式(decorator pattern)設計模式
- 設計模式之組合模式---Composite Pattern設計模式
- JAVA設計模式之 裝飾模式【Decorator Pattern】Java設計模式
- JAVA設計模式之 建造者模式【Builder Pattern】Java設計模式UI
- JAVA設計模式之 原型模式【Prototype Pattern】Java設計模式原型
- JAVA設計模式之 狀態模式【State Pattern】Java設計模式
- JAVA設計模式之 命令模式【Command Pattern】Java設計模式
- JAVA設計模式之 迭代器模式【Iterator Pattern】Java設計模式
- JAVA設計模式之 中介者模式【Mediator Pattern】Java設計模式
- 4/24 設計模式之命令設計模式 Command Pattern設計模式
- 設計模式(四)Singleton設計模式設計模式
- Singleton設計模式設計模式
- 設計模式之介面卡模式(adapter pattern)設計模式APT
- 設計模式之委派模式(Delegate Pattern)深入淺出設計模式
- Java設計模式之裝飾者模式(Decorator pattern)Java設計模式
- JAVA設計模式之 橋接模式【Bridge Pattern】Java設計模式橋接