Design Patterns Explained Java Code Examples – Chapter 21: The Singleton Pattern and the Double-Checked Locking Pattern

Chapter 21: The Singleton Pattern and the Double-Checked Locking Pattern
Code Examples

Example 21-1: Singleton Pattern

TOC

Example 21-2: Singleton Pattern in the context of the e-commerce system

TOC

Example 21-3: Instantiation Only

TOC

Example 21-4: Instantiation Only

TOC


Singleton makes objects responsible for themselves

The Singleton could be implemented in code as shown in Example 21-1. In this example, I create a method (getInstance) that will instantiate at most one USTax object. The Singleton protects against someone else instantiating the USTax object directly by making the constructor private, which means that no other object can access it.

Example 21-1: Singleton Pattern

TOP

public class USTax extends Tax {
    private static USTax instance;
    private USTax() {
    }
    public static USTax getInstance() {
        if (instance== null) instance= new USTax();
        return instance;
    }
}

Singleton with polymorphism

Example 21-2: Singleton Pattern in the context of the e-commerce system

TOP

abstract public class Tax {
    static private Tax instance;
    protected Tax() {
    }
    abstract double calcTax(double qty, double price);
    public static Tax getInstance() {
        // use whatever rule you use to determine
        // which tax object to use. For now, 
        // let's create a USTax object.
        instance= USTax.getInstance();
        return instance;
    }
}
public class USTax extends Tax {
    private static USTax instance;
    private USTax() {
    }
    // Note in the following, I had to change USTax 
    // to Tax since I used the same "getInstance" 
    // name.public static Tax getInstance() {
    if (instance== null) instance= new USTax();
    return instance;
    }
}

Example 21-3: Instantiation Only

TOP

public class USTax extends Tax {
    private static USTax instance;
    private USTax() {
    }
    public static Tax getInstance() {
        if (instance== null) {
             synchronized(this) {
                if (instance == null) instance = new USTax();
            }
        }
        return instance;
    }
    private synchronized static void doSync() {
        if (instance == null)instance = new USTax();
    }
}

A Solution for Java

It is not all that hard to fix this – not that I figured it out on my own. One solution is to take advantage of the class loader, as shown in Example 21-4.

Example 21-4: Instantiation Only

TOP

public class USTax extends Tax {
    private static class Instance {
        static final Tax instance= new USTax();
    }
    private static USTax instance;
    private USTax() {
    }
    public static Tax getInstance() {
        return Instance.instance;
    }
}