Singleton pattern (C++ implementation)

Note: This article refers to the following URL

http://www.cnblogs.com/cxjchen/p/3148582.html

Singleton mode
Singleton mode can be said to be one of the most commonly used patterns in design patterns, and it is said that it is also the interviewer's favorite topic. However, if you have not learned design patterns, you may not think of applying the singleton pattern. In the face of the application of the singleton pattern, you may give priority to the use of global or static variables, which is relatively simple and has never been learned. The easiest way a design pattern person can think of.

Under normal circumstances, some of the classes we build are of the nature of tools, and there is basically no need to store too much data related to themselves. In this case, we need to create a new object every time, which increases the overhead and makes the code more complex. Bloated. In fact, we only need an instance object. If global or static variables are used, encapsulation will be affected, and it is difficult to ensure that other codes will not affect global variables.

Considering these needs, we declare the default constructor as private, so that it will not be new from the outside, and even declare the destructor as private, so that only you can delete yourself. In pure object-oriented languages ​​such as Java and C#, the singleton pattern is very easy to implement. You can directly initialize the instance in the static area and then return it through getInstance. This is called a hungry Chinese-style singleton class. There are also some ways of writing new instance in getInstance and then returning, which is called a lazy singleton class, but this involves a judgment problem of the first getInstance.

The following code is just to show, it has nothing to do with the specific language.

In a single thread:

Singleton* getInstance()
{
    if (instance == NULL)
        instance = new Singleton();

    return instance;
}

That's it, to ensure that only one instance is obtained. But in a multi-threaded environment, it will not work, because it is very likely that two threads will run to the sentence if (instance == NULL) at the same time, resulting in two instances may be generated. So it is necessary to lock in the code.

Singleton* getInstance()
{
    lock();
    if (instance == NULL)
    {
       instance = new Singleton();
    }
    unlock();

    return instance;
}

But if you write it in this way, it will slightly reflect the performance, because every time it is determined whether it is empty or not, it needs to be locked. If there are many threads, it will cause a large number of threads to block. So the great gods came up with a double lock again.

Singleton* getInstance()
{
    if (instance == NULL)
    {
    lock();
        if (instance == NULL)
        {
            instance = new Singleton();
        }
        unlock();
    }

    return instance;
}

In this way, only with a very low probability, the thread that has passed the if (instance == NULL) will have the possibility of entering the locked critical section. This probability is still relatively low and will not block too many threads, but in order to To prevent a thread from entering the critical section to create an instance, another thread also enters the critical section to create an instance, and a defense if (instance == NULL) is added to ensure that it will not be created repeatedly.
image_thumb[3]

Common scenarios
The singleton pattern is often used in conjunction with the factory pattern, because the factory only needs to create a product instance, and it will not cause any conflicts in a multi-threaded environment, so only one factory instance is needed.

Advantages
1. Reduce the overhead of time and space (the overhead of new instances).

2. The encapsulation is improved, making it difficult to change the instance externally.

Disadvantage
1. The lazy style is a way of changing time for space.

2. Hungry Chinese style is a way of exchanging space for time.

C++ implementation code

#ifndef _SINGLETON_H_
#define _SINGLETON_H_


class Singleton{
public:
    static Singleton* getInstance();

private:
    Singleton();
    //把复制构造函数和=操作符也设为私有,防止被复制
    Singleton(const Singleton&);
    Singleton& operator=(const Singleton&);

    static Singleton* instance;
};

#endif


#include "Singleton.h"


Singleton::Singleton(){

}


Singleton::Singleton(const Singleton&){

}


Singleton& Singleton::operator=(const Singleton&){

}


//在此处初始化
Singleton* Singleton::instance = new Singleton();
Singleton* Singleton::getInstance(){
    return instance;
}


#include "Singleton.h"
#include <stdio.h>


int main(){
    Singleton* singleton1 = Singleton::getInstance();
    Singleton* singleton2 = Singleton::getInstance();

    if (singleton1 == singleton2)
        fprintf(stderr,"singleton1 = singleton2\n");

    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324862364&siteId=291194637