设计模式之单例模式

采用了单例模式的类是指,在程序的整个生命周期中,该类只能有唯一一个实例化对象。为此,该类在程序的生命周期中,只能被初始化一次,且不允许有拷贝构造的行为。因此,可以在类的申明中,将构造函数申明为私有的,将拷贝构造和拷贝赋值设置为私有或禁用(=delete)。

先不考虑多线程环境中的线程安全性,单例模式的写法可以分为懒汉模式和饿汉模式。懒汉模式是指,只在真正使用的时候创建实例对象,且保证只会创建一次。饿汉模式是指,在程序初始化时就创建唯一的实例对象。

懒汉模式

#include 
using namespace std;

// 懒汉模式
class Singleton {
public:
    Singleton(Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

    static Singleton* getInstance() {
        if (!instance_) {
            instance_ =  new Singleton();
        }
        return instance_;
    }

private:
    static Singleton* instance_;
    Singleton() {
        cout << "call Singleton once." << endl;
    }
};

Singleton* Singleton::instance_ = nullptr;

int main()
{
    Singleton* s1 = Singleton::getInstance(); 
    Singleton* s2 = Singleton::getInstance();
    if (s1 == s2) {
        cout << "s1 == s2" << endl;
    }
    return 0;
}

程序运行结果:

call Singleton once.
s1 == s2

饿汉模式

#include 
using namespace std;

// 饥饿模式
class Singleton {
public:
    static Singleton* getInstance() {
        return instance_;
    }
private:
    Singleton(const Singleton&);
    Singleton& operator=(const Singleton&);
    Singleton() = default;
    
    static Singleton* instance_;
};

// 和懒汉不同的是,程序在初始化时,就会创建该唯一实例
Singleton* Singleton::instance_ = new Singleton();

int main()
{
    Singleton* s1 = Singleton::getInstance(); 
    Singleton* s2 = Singleton::getInstance();
    if (s1 == s2) {
        cout << "s1 == s2" << endl;
    }
    return 0;
}

线程安全

饿汉模式在多线程环境中是线程安全的,饿汉模式在程序初始化的过程中就创建了全局唯一的实例,因此在程序的整个生命周期中都只有唯一的实例对象。二饥懒汉模式只在第一次调用时才会创建实例对象,因此在多线程环境中,若该类的实例对象还未创建,且同一时刻有多个线程正在同时调用 getInstance 函数,尝试创建实例对象,就会创建出多个实例对象,不符合单例模式规范。

加锁实现线程安全的懒汉模式

// 懒汉模式
class Singleton {
public:
    static Singleton* getInstance() {
        if (instance_ == nullptr) {
            pthread_mutex_lock(&lock_);
            // 需要在判断是否为 nullptr
            if (instance_ == nullptr) {
                instance_ = new Singleton();
            }
            pthread_mutex_unlock(&lock_);
        }
        return instance_;
    }

private:
    Singleton(const Singleton&);
    Singleton& operator=(const Singleton&);
    Singleton() {
        cout << "Singleton call once." << endl;
    }
    
    static pthread_mutex_t lock_;
    static Singleton* instance_;
};

pthread_mutex_t Singleton::lock_ = PTHREAD_MUTEX_INITIALIZER;
Singleton* Singleton::instance_ = nullptr;

局部静态变量

C++11之后编译器保证了内部静态变量的线程安全性。

// 懒汉模式
class Singleton {
public:
    static Singleton* getInstance() {
        static Singleton instance_;
        return &instance_;
    }

private:
    Singleton() = default;
    Singleton (const Singleton&);
    Singleton& operator=(const Singleton&);
};

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