C++设计模式:单例模式

C++设计模式:单例模式

单例模式概述

​ 单例模式是指在整个系统的生命周期里,保证一个类只能产生一个实例,确保该类的 唯一性

单例模式分类

​ 单例模式可以分为 懒汉式饿汉式 ,两者之间的区别在于 创建实例的时间不同

  • 懒汉式:指在系统运行中,实例并不存在,只有当需要使用该实例时,才会去创建并使用该实例。(注:此方式主要考虑线程安全)
  • 饿汉式:指系统统一运行时,就初始化创建实例,当需要时,直接调用即可。(注:此方法本身就已经实现线程安全,没有多线程的问题)

单例模式特点

  • 构造函数和析构函数为private类型,目的是禁止外部构造和析构
  • 拷贝构造和赋值构造函数为private类型,目的是禁止外部拷贝和赋值,确保实例的唯一性
  • 类里有个获取实例的静态函数,可以全局访问

总结:将该类的构造,析构,拷贝构造和赋值构造全部声明为private,提供一个获取静态实例的方法

单例模式作用

​ 为什么要使用单例模式首先得解释什么是线程安全

线程安全是什么?

​ 在拥有共享数据多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外的情况

如何保证线程安全?
  1. 给系统中共享的资源加把,保证每个资源变量每时每刻至多被一个线程占用
  2. 让线程本身也拥有自己的资源,不用去共享进程中的资源

单例模式实现方式

普通懒汉式单例(线程不安全,不推荐使用)
#include 
#include 
#include 

// 线程不安全
// 懒汉式单例模式
class SingleInstance {

    public:
        // 获取静态单例对象
        static SingleInstance* getInstance();

        // 释放单例对象资源
        static void deleteInstance();

        // 其他功能函数....

    private:
        // 将其构造和析构函数声明为私有的,禁止外部构造和析构
        SingleInstance();
        ~SingleInstance();

        // 将其拷贝构造和赋值构造声明为私有的,禁止外部拷贝和赋值
        SingleInstance(const SingleInstance& single);
        const SingleInstance &operator = (const SingleInstance& single);

    private:
        // 唯一的静态单例对象指针
        static SingleInstance* m_SingleInstance;
};
#include "SingleInstance.h"

//初始化静态成员变量
SingleInstance* SingleInstance::m_SingleInstance = NULL;

SingleInstance* SingleInstance::getInstance() {
    if(m_SingleInstance == NULL) {
        // 没有加锁是不安全的,当出现线程并发的时候可能会创建多个实例,不符合单例模式要求
         m_SingleInstance = new (std::nothrow) SingleInstance;
    }
    return m_SingleInstance;
}

void SingleInstance::deleteInstance() {
    // 若单例对象存在,则释放此资源
    if(m_SingleInstance) {
        delete m_SingleInstance;
        m_SingleInstance = NULL;
    }
}

SingleInstance::SingleInstance() {
}

SingleInstance::~SingleInstance() {
}
加锁懒汉式单例(线程安全)
#include 
#include 
#include 

// 线程安全
// 懒汉式单例模式
class SingleInstance {

    public:
        // 获取静态单例对象
        static SingleInstance* & getInstance();

        // 释放单例对象资源
        static void deleteInstance();

        // 其他功能函数....

    private:
        // 将其构造和析构函数声明为私有的,禁止外部构造和析构
        SingleInstance();
        ~SingleInstance();

        // 将其拷贝构造和赋值构造声明为私有的,禁止外部拷贝和赋值
        SingleInstance(const SingleInstance& single);
        const SingleInstance &operator = (const SingleInstance& single);

    private:
        // 唯一的静态单例对象指针
        static SingleInstance* m_SingleInstance;
        static std::mutex m_Mutex;
};
#include "SingleInstance.h"

//初始化静态成员变量
SingleInstance* SingleInstance::m_SingleInstance = NULL;
std::mutex SingleInstance::m_Mutex;

SingleInstance* & SingleInstance::getInstance() {
    //  这里使用了两个 if判断语句的技术称为双检锁;好处是,只有判断指针为空的时候才加锁
    //  避免每次调用 GetInstance的方法都加锁,锁的开销毕竟还是有点大的
    if(m_SingleInstance == NULL) {
        std::unique_lock lock(m_Mutex); // 加锁
        if(m_SingleInstance == NULL) {
            m_SingleInstance = new (std::nothrow) SingleInstance;
        }
    }

    return m_SingleInstance;
}

void SingleInstance::deleteInstance() {
    std::unique_lock lock(m_Mutex); // 加锁
    if(m_SingleInstance) {
        delete m_SingleInstance;
        m_SingleInstance = NULL;
    }
}

SingleInstance::SingleInstance() {
}

SingleInstance::~SingleInstance() {
}
内置静态变量懒汉单例(C++11,线程安全)
// 线程安全
// 内置静态变量懒汉式单例模式

class SingleInstance {

    public:
        // 获取静态单例对象
        static SingleInstance & getInstance();

        // 其他功能函数....

    private:
        // 将其构造和析构函数声明为私有的,禁止外部构造和析构
        SingleInstance();
        ~SingleInstance();

        // 将其拷贝构造和赋值构造声明为私有的,禁止外部拷贝和赋值
        SingleInstance(const SingleInstance& single);
        const SingleInstance &operator = (const SingleInstance& single);
};
#include "SingleInstance.h"

SingleInstance & SingleInstance::getInstance() {
    // 局部静态特性的方式实现单实例
    static SingleInstance signal;
    return signal;
}

SingleInstance::SingleInstance() {
}

SingleInstance::~SingleInstance() {
}
饿汉式单例
class SingleInstance {
    
    public:
        // 获取单实例
        static SingleInstance* getInstance();

        // 释放单实例
        static void deleteInstance();

        // 其他功能函数....

    private:
        // 将其构造和析构函数声明为私有的,禁止外部构造和析构
        SingleInstance();
        ~SingleInstance();

        // 将其拷贝构造和赋值构造声明为私有的,禁止外部拷贝和赋值
        SingleInstance(const SingleInstance& single);
        const SingleInstance &operator = (const SingleInstance& single);

    private:
        // 唯一的静态单例对象指针
        static SingleInstance* m_SingleInstance;
};
#include "SingleInstance.h"

SingleInstance* SingleInstance::m_SingleInstance = new (std::nothrow) SingleInstance;

SingleInstance* SingleInstance::getInstance() {
    return m_SingleInstance;
}

SingleInstance::SingleInstance() {
}

SingleInstance::~SingleInstance() {
}
二者的区别与特点
  • 懒汉式以时间换空间,适应于访问量较小时;推荐使用内部静态变量的懒汉单例,代码量少
  • 饿汉式以空间换时间,适应与访问量较大时,或者线程比较多的情况

单例模板实现

​ 单例模式的应用场景很多,例如:替换任意的全局变量;配置文件;设备管理器;数据池等

​ 我们可以通过模板的形式,写出一个单例模式的模板类以友元的形式加入其他类中,方便之后其他类的套用

// 单例模板
template 
class Singleton {
    // 获取静态单例对象
    static T* getInstance();

    private:
    // 将其构造和析构函数声明为私有的,禁止外部构造和析构
    Singleton() {}
    ~Singleton() {}

    // 将其拷贝构造和赋值构造声明为私有的,禁止外部拷贝和赋值
    Singleton(const Singleton&);
    const Singleton &operator = (const Singleton &);

    private:
        static T* m_instance;
};

template 
T* Singleton::m_instance = new (std::nothrow) Singleton;
#include "Singleton.h"

class Single {

    friend class Singleton;

    public:
        // 其他功能函数...

    private:
        // 将其构造和析构函数声明为私有的,禁止外部构造和析构
        Single() {}
        ~Single() {}

        // 将其拷贝构造和赋值构造声明为私有的,禁止外部拷贝和赋值
        Single(const Single&);
        const Single &operator = (const Single &);

    private:
        // 类自身数据成员

};

你可能感兴趣的:(C++学习,设计模式,单例模式,c++,设计模式)