Editing Combined Patterns New

Singleton


Objective

Ensure the creation of a single instance for a given class.

Function

Ensure the existence of a single instance for a class and the creation of a mechanism for global access to it.

Structure

As shown in figure 1

The Singleton class declares the static method obtainInstance that returns the same instance of its own class. The Singleton constructor must be hidden from the customer's code. Calling the getInstance method should be the only way to get the Singleton object.

The structure that meets this pattern is shown in Figure 1

Responsive image

Figure 1: UML Diagram Singleton Pattern

Applications

  • The system requires exactly one instance of a class, which must be accessible to customers from a well-defined access point.

  • The single instance must be extended to subclasses and clients must be able to use it without modifying their code.

Design Patterns Collaborators

  • A Singleton pattern is often related to and used in the implementation of the Abstract Factory pattern, especially when it concerns a specific factory.

Scope of action

Applied at the object level.

Problem

Ensuring the creation of a single instance requires high levels of validation and a global variable; which is difficult to control when there are multiple instances of objects.

Solution

The Singleton pattern creates a class that instances the only object that will be responsible for the creation, initialization and access; this instance must be a private, since the instance creation operation must be hidden. In addition, the requires a static public function that takes care of the encapsulation of the initialization and provides a global access point. In the implementation process The employer must ensure that each class is responsible for monitoring that no allow more than one instance.

Diagram or Implementation

Responsive image

Figure 2: UML Diagram Singleton Pattern

Figure 2 explains the behaviour of the pattern by means of a sequence diagram.

  • Client class requests the instance from the Singleton class by means of the static method obtainInstance().

  • The Singleton class will validate if the instance was already created before, if not then a new one is created.

  • The instance created in the previous step is returned or the existing instance is returned in another case.


Study Cases


Printer System
Responsive image

Figure 3: UML Diagram Printer System


Responsive image

Figure 4: UML Diagram Printer System



Bank System
Responsive image

Figure 5: UML Diagram Bank System


Responsive image

Figure 6: UML Diagram Bank System


Implementations of the singleton pattern:

    	
    		
class SingletonMeta(type):
    """
    The Singleton class can be implemented in different ways in Python. Some
    possible methods include: base class, decorator, metaclass. We will use the
    metaclass because it is best suited for this purpose.
    """

    _instances = {}

    def __call__(cls, *args, **kwargs):
        """
        Possible changes to the value of the `__init__` argument do not affect
        the returned instance.
        """
        if cls not in cls._instances:
            instance = super().__call__(*args, **kwargs)
            cls._instances[cls] = instance
        return cls._instances[cls]


class Singleton(metaclass=SingletonMeta):
    def some_business_logic(self):
        """
        Finally, any singleton should define some business logic, which can be
        executed on its instance.
        """

        # ...


if __name__ == "__main__":
    # The client code.

    s1 = Singleton()
    s2 = Singleton()

    if id(s1) == id(s2):
        print("Singleton works, both variables contain the same instance.")
    else:
        print("Singleton failed, variables contain different instances.")    	
    	
    	
    		
namespace RefactoringGuru\Singleton\Conceptual;

/**
 * The Singleton class defines the `GetInstance` method that serves as an
 * alternative to constructor and lets clients access the same instance of this
 * class over and over.
 */
class Singleton
{
    /**
     * The Singleton's instance is stored in a static field. This field is an
     * array, because we'll allow our Singleton to have subclasses. Each item in
     * this array will be an instance of a specific Singleton's subclass. You'll
     * see how this works in a moment.
     */
    private static $instances = [];

    /**
     * The Singleton's constructor should always be private to prevent direct
     * construction calls with the `new` operator.
     */
    protected function __construct() { }

    /**
     * Singletons should not be cloneable.
     */
    protected function __clone() { }

    /**
     * Singletons should not be restorable from strings.
     */
    public function __wakeup()
    {
        throw new \Exception("Cannot unserialize a singleton.");
    }

    /**
     * This is the static method that controls the access to the singleton
     * instance. On the first run, it creates a singleton object and places it
     * into the static field. On subsequent runs, it returns the client existing
     * object stored in the static field.
     *
     * This implementation lets you subclass the Singleton class while keeping
     * just one instance of each subclass around.
     */
    public static function getInstance(): Singleton
    {
        $cls = static::class;
        if (!isset(self::$instances[$cls])) {
            self::$instances[$cls] = new static();
        }

        return self::$instances[$cls];
    }

    /**
     * Finally, any singleton should define some business logic, which can be
     * executed on its instance.
     */
    public function someBusinessLogic()
    {
        // ...
    }
}

/**
 * The client code.
 */
function clientCode()
{
    $s1 = Singleton::getInstance();
    $s2 = Singleton::getInstance();
    if ($s1 === $s2) {
        echo "Singleton works, both variables contain the same instance.";
    } else {
        echo "Singleton failed, variables contain different instances.";
    }
}

clientCode();    	
    	
    	
    		
package refactoring_guru.singleton.example.non_thread_safe;

public final class Singleton {
    private static Singleton instance;
    public String value;

    private Singleton(String value) {
        // The following code emulates slow initialization.
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        this.value = value;
    }

    public static Singleton getInstance(String value) {
        if (instance == null) {
            instance = new Singleton(value);
        }
        return instance;
    }
}