Creational mode - singleton mode (Singleton)

Ensures that there is only one instance of a class and provides a global access point to it.

Application scenario:

  • When there is only one instance of a class and clients can access it from a well-known access point;
  • when the unique instance should be extensible through subclassing, and clients should be able to use an extended instance without code changes;

example:

1. Commonly used singletons

class Singleton
{
public:
    static Singleton* getSingleton()
    {
        if(singleton == nullptr)
        {
            singleton = new Singleton();            
        }
        return singleton;
    }
    void show() { cout << "Singleton" << endl; }
    
private:
    static Singleton *singleton;

    Singleton(){}
    Singleton(Singleton&) = delete;
    Singleton& operator=(Singleton&) = delete;
};

Singleton *Singleton::singleton = nullptr;

The simple version of the singleton mode is implemented by creating a static pointer at compile time, creating a dynamic object when calling new, and then returning the static pointer to achieve object acquisition. In order to ensure global uniqueness, the constructor needs to be made private and copying is prohibited Construction and assignment functions.

2. Template singleton mode

template<class T>
class Singleton
{ public:     static T& getSingleton()     {         static T singleton; //Multiple calls will only instantiate once         return singleton;     }    





protected:
    Singleton() { cout << "Singleton::Singleton()" << endl; } //In order for the derived class to inherit, the instance can call the constructor

private:    
    Singleton(Singleton&) = delete;
    Singleton& operator=(Singleton&) = delete;
};

class A : public Singleton<A>
{ public:     friend class Singleton<A>; //In order for the base class to be able to call the private member functions and variables of the derived class

    void showA() { cout << "A::showA()" << endl; }

private:
    A(A&) = delete;
    A& operator=(A&) = default;
    A():Singleton<A>(){ cout << "A::A()" << endl; };
};

void doSingletonPattern()
{
    A &a1 = Singleton<A>::getSingleton();
    A &a2 = Singleton<A>::getSingleton();
    a1.showA();
    a2.showA();
    cout << "a1==" << &a1 << "\ta2==" << &a2 << endl;
}

The template version of the singleton pattern is summarized into a framework by extracting the common parts of the simple version of the singleton pattern. Any class that inherits the base class is a singleton pattern, which realizes the template of the singleton pattern. The main point of implementation is to create a static pointer and point to an object space created by new in the return function, and then return the object pointer. Since the derived class object is instantiated in the base class, the base class needs to call the constructor of the derived class. Since the derived class constructor is private, it is necessary to declare the base class as private in the derived class; at the same time, the derived class calls the constructor When using a function, the base class constructor needs to be called, so the base class constructor must be declared as a protected type so that it can be inherited and called by the derived class; the difference between the simple
version and the template version of the singleton mode:
the main difference between the two lies in instantiating objects way. The simple version instantiates the object directly and then returns the static pointer, just call the returned pointer directly; while the template version instantiates the derived class in the base class template (the derived class passes its own type into the base class), because the base class To call the derived class constructor, you need to declare the base class as a friend class in the derived class; and when the derived class calls the constructor, you need to call the base class constructor first, so you need to inherit the base class constructor, so the base class constructor Functions must be declared protected.
In short, the main logic is: the base class instantiates the derived class object --> the base class needs to call the derived class constructor (the base class is declared as a friend class in the derived class) --> the derived class must first call the base class constructor ( The base class constructor is declared protected)

Guess you like

Origin blog.csdn.net/rukawashan/article/details/124486174