Linux (thirteen) design pattern - singleton pattern

 Design patterns - special processing solutions designed for typical scenarios

Singleton mode: a class can only instantiate one object (so called a singleton)

        Scenes:

                1. Resource perspective: resources only occupy one copy in memory

                2. Data perspective: If there is only one object, it is consistent when the object accesses its resources

Table of contents

 Method to realize

1. Hungry man mode

2. Lazy Mode


Just like the task manager, no matter how many times I open it, it only has this task manager.

 Method to realize

 1. Hungry man mode

The so-called Hungry Man mode directly instantiates the object and uses it directly when it is used (space for time)

        Benefits: Maximize efficiency, use resources directly when they are used (no thread safety issues involved)

        Disadvantages: slow initialization speed, large memory usage

Implementation: Use static member variables (to ensure that it can have a copy of memory when it is initialized)

           Make the constructor private (objects cannot be instantiated outside the class, and there can only be one copy of the object)

           Provide public interface for access

#include <iostream>

class Singleton
{
private:
    int _data;

private:
    static Singleton eton;
    Singleton() // 将构造函数私有化,意味着在类外无法实例化对象
    {           // 保证一个类只能实例化一个对象(构造函数私有化,该类也无法被继承)
        // 逻辑处理begin
        _data = 100;
        // 逻辑处理end
    }

public:
    static Singleton *GetInstence() // 静态成员只能被静态成员函数调用
    {
        return &eton;
    }
    int Get_data()    // 提供一个获取data的方法
    {
        return _data;
    }
};

// 静态成员变量,类内声明、类外定义
Singleton Singleton::eton;

int main()
{
    Singleton *eton = Singleton::GetInstence();
    std::cout << eton->Get_data() << std::endl;

    return 0;
}

2. Lazy Mode

The so-called lazy man mode is to construct and instantiate when waiting for use

        Advantages: less memory resource occupation, high initialization efficiency

        Disadvantages: When you need to access resources, you need to instantiate object loading (the object is slower when you first access it) (involving thread safety issues)

accomplish:

        1. Constructor privatization (guaranteed that only one object can be instantiated)

        2. Define the pointer of static type, and perform new when using it

        3. Pay attention to thread safety issues when new (lock protection)

        4. Avoid repeated access to subsequent resources after instantiation (double check)

        5. Use volatile modification to avoid over-optimization by the compiler

                Volatile: When a variable is frequently accessed by the CPU, put the variable into a register, so that for such a frequently accessed variable, the CPU can directly access it from the register, avoiding getting data back and forth from the memory.

#include <iostream>
#include <mutex>

class Singleton
{
private:
    int _data;

private:
    static Singleton *_eton; // 1、定义静态的指针与锁
    static std::mutex _mutex;
    Singleton() /// 2、构造函数私有化(只能被实例化一次)
    {
        // 逻辑处理begin
        _data = 100;
        // 逻辑处理end
    }

public:
    int get_data() { return _data; }
    static Singleton *GetInsetnce()
    {
        if (_eton == nullptr) // 5、double check避免了已经实例化了还需要加解锁问题
        {
            _mutex.lock(); /// 4、使用mutex进行安全控制
            if (_eton == nullptr)
                _eton = new Singleton; // 3、等到用的时候进行new 调用构造实例化
            _mutex.unlock();
        }
        return _eton;
    }
};
// 6、对其构造和声明使用volatile修饰 保证数据的可见性
// volatile Singleton *Singleton::_eton = nullptr;
Singleton *Singleton::_eton = nullptr;
std::mutex Singleton::_mutex;

int main()
{
    Singleton *eton = Singleton::GetInsetnce();
    std::cout << eton->get_data() << std::endl;
}

 

Guess you like

Origin blog.csdn.net/weixin_66151870/article/details/129099241