设计模式学习笔记1——单例模式

单例模式(Singleton)

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

代码:https://github.com/duyilong/Design-pattern/tree/master/Singleton

  • 保证仅有一个实例:不允许随意new,将构造函数复制构造函数赋值运算符声明为私有private,注意,析构函数也要声明为私有。
  • 全局访问点:静态的GetInstance方法、静态的DeleteInstance方法。

根据instance创建的时间分为饿汉式和懒汉式两种实现方式。

饿汉式:the Singleton instance is EARLY createed at compile time。

懒汉式:the Singleton instance is LAZILY created at runtime。

先看代码,

1. 线程安全单例类的懒汉式实现

#include <mutex> //std::mutex

class Singleton_lazy
{
public:
    static Singleton_lazy *&GetInstance() ; //注意返回值类型,对一个指针变量的引用
    static void DeleteInstance();

private:
    Singleton_lazy() {}
    ~Singleton_lazy() {}
    Singleton_lazy(const Singleton_lazy &singleton) {}
    const Singleton_lazy operator=(const Singleton_lazy &singleton) {}

private:
    static Singleton_lazy *m_instance;
    static std::mutex m_mutex;
};

// 初始化静态成员变量
Singleton_lazy *Singleton_lazy::m_instance = NULL;
std::mutex      Singleton_lazy::m_mutex;

// 成员函数实现
Singleton_lazy *&Singleton_lazy::GetInstance()
{
    if (m_instance == NULL) //双重锁定,防止每次调用GetInstance都要加锁,只有发现需要实例化的时候才加锁
    {
        //如果两个线程同时通过了第一重的m_instance==NULL判断,就会有一个先加锁然后创建出来m_instance。
        //所以还需要第二重判断m_instance==NULL,防止被实例化出多个对象
        std::unique_lock<std::mutex> lock(m_mutex); //加锁
        if (m_instance == NULL)                     //
        {
            m_instance = new Singleton_lazy;
        }
    }
    return m_instance;
}

void Singleton_lazy::DeleteInstance()
{
    std::unique_lock<std::mutex> lock(m_mutex);
    if (m_instance)
    {
        delete m_instance;
        m_instance = NULL;
    }
}

注意:

  1. GetInstance方法的返回类型。对一个指针变量的引用,可行;指向引用的指针,不对。
  2. GetInstance方法的双重锁定。
  3. 在类的声明体外对static成员变量进行定义和初始化。(注意:对于一般的类,可以只在类体外对static成员定义,然后在构造函数中初始化。注意区分声明、定义和初始化的区别。声明 [声明语句为类体内的static std::mutex m_mutex] 不会给变量分配内存空间,定义 [定义语句为类体外的std::mutex Singleton_lazy::mutex; 对instance变量的定义和初始化在同一个语句中] 才会给变量分配内存空间。)

2.C++11线程安全单例类的懒汉式实现

class Single
{
public:
    // 获取单实例对象
    static Single &GetInstance()
    {
        // c++11内部静态变量具有线程安全性,所以可以利用这个特性很简单就实现一个线程安全的单例类
        // 局部静态特性的方式实现单实例
        static Single instance;
        return instance;
    }

private:
    Single();                                      // 禁止外部构造
    ~Single();                                     // 禁止外部析构
    Single(const Single &signal);                  // 禁止外部复制构造
    const Single &operator=(const Single &signal); // 禁止外部赋值操作
};

3.单例类的饿汉式实现(天生线程安全)

饿汉式利用语言运行时库的“静态初始化”特性,在单例类的实现代码一加载到程序中的时候,就在内存中实例化出了一个单例类的实例。

// 单例类饿汉式实现
// 本身具有线程安全性
#include <iostream>
using namespace std;

namespace myspace
{

class singleton_early
{
public:
    static singleton_early *GetInstance()
    {
        return g_psingle;
    }

    static void DeleteInstance()
    {
        if (g_psingle)
        {
            delete g_psingle;
            g_psingle = NULL;
        }
    }

    void test()
    {
        printf("test early singleton\n");
    }

private:
    singleton_early() {}
    ~singleton_early() {}
    singleton_early(const singleton_early &single) {}
    const singleton_early &operator=(const singleton_early &single) {}

private:
    static singleton_early *g_psingle;
};

// 静态成员变量的初始化
singleton_early *singleton_early::g_psingle = new singleton_early;
} // namespace myspace

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章