Skip to content

Latest commit

 

History

History

singleton

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

The Singleton Pattern ensures a class has only one instance, and provides a global point of access of it.

Although the Singleton is the simplest in terms of its class diagram, it is difficult to get it right due to multi-threads. In Java, a quick fix-up is to add the synchronized keywords. But we can also note that after the first time through, synchronization is totally unneeded overhead.

public static synchronized Singleton getInstance() {
    if (uniqueInstance == null) {
        uniqueInstance = new Singleton();
    }
    return uniqueInstance;
}

An alternative is to move to an early crated instance:

private static final Singleton uniqueInstance = new Singleton();

public static Singleton getInstance() {
    return uniqueInstance;
}

We can also use double-checked locking:

private volatile static Singleton uniqueInstance;

public static Singleton getInstance() {
    if (uniqueInstance == null) {
        synchronized (Singleton.class) {
            if (uniqueInstance == null) {
                uniqueInstance = new Singleton();
            }
        }
    }
}

HFDP Book, as well as Effective Java, also provide a better approach:

a single-element enum type is often the best way to implement a singleton.

Back at Rust, the good thing is that it provides better concurrency guarantee, and the bad thing is that static filed is not allowed in structures. It is highly recommended to use lazy_static if you want to use static. As for the Singleton pattern, we also adopt the enum type as the implementation.

pub enum Singleton {
    INSTANCE,
}

What's more, we can also attach data to the enum if necessary.

pub enum Singleton {
    INSTANCE(String),
}