创建型模式——单例(singleton)

1. 模式说明

单例模式保证类只有一个实例;创建一个对象,当你创建第二个对象的时候,此时你获取到的是已经创建过的对象,而不是一个新的对象;

1.1 使用场景

共享资源的访问权限;任务的管理类;数据库的操作等;

1.2 要素

  • 私有化类的构造函数;
  • 使用类的私有静态指针变量指向类的唯一实例
  • 公有静态方法获取该实例;

1.3 类型

  • 懒汉模式
  • 饿汉模式

2. 懒汉模式

单例实例在第一次被使用时才进行初始化,延迟初始化

2.1 基本

示例

/*
 * @brief         : design patterns singleton
 * @author        : your name
 * @compile       : g++ -g singleton_main.cc -o d -std=c++11
 * @date          : 2023/04/18
 * @lastEditorDate:   
 */

#include <iostream>
#include <string>

//懒汉模式
class Singleton
{
    
    
public:
    static Singleton*  getSingletonInstance()   //访问函数
    {
    
    
        if(instance == nullptr)
        {
    
    
            instance = new Singleton;
        }
        return instance;
    }

public:
    void addCount() {
    
    
        m_count++;
    }

    int32_t getCount() {
    
    
        return m_count;
    }
    

private:
    static Singleton* instance;    //静态指针变量
    Singleton(){
    
    }    //私有化类的构造函数
    int32_t m_count{
    
    0};
};

Singleton* Singleton::instance = nullptr;    //静态成员类外初始化

int main(int argc, char* argv[])
{
    
    
    Singleton* single_0 = Singleton::getSingletonInstance();
    single_0->addCount();
    std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl<<std::endl;

    Singleton* single_1 = Singleton::getSingletonInstance();
    single_1->addCount();
    std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl;
    std::cout<<"single_1 value is: "<<single_1->getCount()<<std::endl<<std::endl;    

    return 0;
}

输出

single_0 value is: 1

single_0 value is: 2
single_1 value is: 2

2.2 线程安全

2.1中的示例是线程不安全的,假如有多个线程同时调用getSingletonInstance(),此时检测到instance是nullptr,就会导致单例的崩溃,造成内存泄漏;

通过加锁来实现
示例

/*
 * @brief         : design patterns singleton
 * @author        : your name
 * @compile       : g++ -g singleton_main.cc -o d -std=c++11
 * @date          : 2023/04/18
 * @lastEditorDate:   
 */

#include <iostream>
#include <string>
#include <mutex>

//懒汉模式
std::mutex mtx;  //全局的锁
class Singleton
{
    
    
public:
    static Singleton*  getSingletonInstance()   //访问函数
    {
    
    
        if(instance == nullptr)
        {
    
    
            std::lock_guard<std::mutex> guard(mtx); 
            if(instance == nullptr)
            {
    
    
                instance = new Singleton;
            }            
        }
        return instance;
    }

public:
    void addCount() {
    
    
        m_count++;
    }

    int32_t getCount() {
    
    
        return m_count;
    }
    
private:    
    static Singleton* instance;    //静态指针变量
    Singleton(){
    
    }    //私有化类的构造函数
    int32_t m_count{
    
    0};
};
Singleton* Singleton::instance = nullptr;    //静态成员类外初始化

int main(int argc, char* argv[])
{
    
    
    Singleton* single_0 = Singleton::getSingletonInstance();
    single_0->addCount();
    std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl<<std::endl;

    Singleton* single_1 = Singleton::getSingletonInstance();
    single_1->addCount();
    std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl;
    std::cout<<"single_1 value is: "<<single_1->getCount()<<std::endl<<std::endl;    

    return 0;
}

输出

single_0 value is: 1

single_0 value is: 2
single_1 value is: 2

使用 c++11 中局部静态变量是线程安全的性质

示例

/*
 * @brief         : design patterns singleton
 * @author        : your name
 * @compile       : g++ -g singleton_main.cc -o d -std=c++11
 * @date          : 2023/04/18
 * @lastEditorDate:   
 */

#include <iostream>
#include <string>
#include <mutex>

//懒汉模式
class Singleton
{
    
    
public:
    static Singleton* getSingletonInstance()   //访问函数
    {
    
    
        static Singleton instance;    //静态指针变量
        return &instance;
    }

public:
    void addCount() {
    
    
        m_count++;
    }

    int32_t getCount() {
    
    
        return m_count;
    }
    

private:  
    Singleton(){
    
    }    //私有化类的构造函数
    int32_t m_count{
    
    0};
};

int main(int argc, char* argv[])
{
    
    
    Singleton* single_0 = Singleton::getSingletonInstance();
    single_0->addCount();
    std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl<<std::endl;

    Singleton* single_1 = Singleton::getSingletonInstance();
    single_1->addCount();
    std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl;
    std::cout<<"single_1 value is: "<<single_1->getCount()<<std::endl<<std::endl;    

    return 0;
}

输出

single_0 value is: 1

single_0 value is: 2
single_1 value is: 2

3. 饿汉模式

指单例实例在程序运行时被立即执行初始化

示例

/*
 * @brief         : design patterns singleton
 * @author        : your name
 * @compile       : g++ -g singleton_main.cc -o d -std=c++11
 * @date          : 2023/04/18
 * @lastEditorDate:   
 */

#include <iostream>
#include <string>
#include <mutex>

//饿汉模式
class Singleton
{
    
    
public:
    static Singleton*  getSingletonInstance()   //访问函数
    {
    
            
        return instance;
    }

public:
    void addCount() {
    
    
        m_count++;
    }

    int32_t getCount() {
    
    
        return m_count;
    }
    

private:
    static Singleton* instance;    //静态指针变量
    Singleton(){
    
    }    //私有化类的构造函数
    int32_t m_count{
    
    0};
};

Singleton* Singleton::instance = new Singleton;    //静态成员类外初始化

int main(int argc, char* argv[])
{
    
    
    Singleton* single_0 = Singleton::getSingletonInstance();
    single_0->addCount();
    std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl<<std::endl;

    Singleton* single_1 = Singleton::getSingletonInstance();
    single_1->addCount();
    std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl;
    std::cout<<"single_1 value is: "<<single_1->getCount()<<std::endl<<std::endl;    

    return 0;
}

输出

single_0 value is: 1

single_0 value is: 2
single_1 value is: 2

4. 在开发过程中的使用

在项目的使用过程中,可以将单例设计成为类模板;这样其它类在设计的时候不用考虑,是否需要将其设计成为单例;

其它类如果需要单例属性,只需要通过单例模板对其进行赋能即可;

示例

/*
 * @brief         : design patterns singleton
 * @author        : your name
 * @compile       : g++ -g singleton_main.cc -o d -std=c++11
 * @date          : 2023/04/18
 * @lastEditorDate:   
 */

#include <iostream>
#include <string>
#include <mutex>

template<class T>
class Singleton
{
    
    
public:
    static T* getSingletonInstance()   //访问函数
    {
    
    
        static T instance;    //静态指针变量
        return &instance;
    }
private:  
    Singleton(){
    
    }    //私有化类的构造函数
};

class C1
{
    
    
public:
    void addCount() {
    
    
        m_count++;
    }

    int32_t getCount() {
    
    
        return m_count;
    }    

private:    
    int32_t m_count{
    
    0};
};

int main(int argc, char* argv[])
{
    
    
    auto re1 = Singleton<C1>::getSingletonInstance();
    re1->addCount();
    std::cout<<"re1->getCount() value is: "<<re1->getCount()<<std::endl;

    auto re2 = Singleton<C1>::getSingletonInstance();
    re2->addCount();
    std::cout<<"re1->getCount() value is: "<<re1->getCount()<<std::endl;
    std::cout<<"re2->getCount() value is: "<<re2->getCount()<<std::endl;

    return 0;
}

输出


re1->getCount() value is: 1
re1->getCount() value is: 2
re2->getCount() value is: 2

猜你喜欢

转载自blog.csdn.net/shouhu010/article/details/130214252