单例模式(Singleton Pattern)

单例模式设计到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一对象的方式,可以直接访问,不需要实例化该类的对象。

 注意:

单例类只能有一个实例。

单例类必须自己创建自己的唯一实例。

单例类必须给所有其他对象提供这一实例。

 

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

主要解决:一个全局使用的类频繁地创建于销毁。

何时使用:控制实例数目,节省系统资源的时候。

如何解决:判断系统时候已经有这个单例,如果有则返回,如果没有则创建。

关键代码:构造函数是私有的。

实例:1、一个班级只有一个班主任。

           2、一些设备管理器设计为单例模式,

优点:1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例

           2、避免对资源的多重占用。

缺点:没有接口,不能继承,与单一职责原则冲突。

使用场景:1、要求生产唯一序列号。

                  2、创建的一个对象需要消耗的资源过多,比如I/O与数据库的连接等。

 

 

C++代码实现:

1、懒汉式是使用到时才实例化对象,在调用到getInstance()方法时才会new出一个单例对象。

可能会带来的问题:

#include<iostream>
#include<memory>
#include<mutex>
using namespace std;

//创建懒汉单例类
class SingleObject {
public:
    typedef shared_ptr<SingleObject> ptr;
    ~SingleObject()
    {
        cout << "析构函数~!~!" << endl;
    }
    //C++11 关键字delete 表民绝对禁止使用拷贝构造函数
    SingleObject(SingleObject&) = delete;
    SingleObject& operator=(const SingleObject&) = delete;

    static SingleObject* getInstance()
    {
        if (instance == nullptr)
        {
            instance = new SingleObject;
        }
        return instance;
    }

private:
    SingleObject()
    {
        cout << "构造函数~!~!" << endl;
    }
    static SingleObject* instance;
};
//类的数据成员不能在类的声明体中初始化
//必须在类外进行初始化
SingleObject* SingleObject::instance = nullptr;

int main()
{
    SingleObject* ins = SingleObject::getInstance();
    SingleObject* ins_2 = SingleObject::getInstance();
    //SingleObject* ins_3 = new SingleObject;    //编译无法通过
    
    system("pause");
    return 0;
}

1、线程安全问题:在多线程环境下,假设存在两个线程同时调用到getInstance()方法。第一个线程判断isnstance==nullptr,于是实例化单例;此时第二个线程判断isnstance==nullptr,于是也开始实例化单例。这样就不能保证单例的唯一性。

解决办法:加锁。

2、内存泄漏:类中只负责new出对象,却没有负责delete对象。析构函数中却没有被调用,所以会导致内存泄漏。

解决办法:使用共享指针(shared_ptr)。

  为什么不在析构函数中调用delete?自己在思考:static成员函数中new出的对象可以在析构函数中delete吗?

                                        

2、线程安全、内存安全的懒汉单例模式

#include<iostream>
#include<memory>
#include<mutex>
using namespace std;
//创建线程安全、内存安全的懒汉类
class SingleObject {
public:
    //为shared_ptr定义一个别名Ptr
    typedef shared_ptr<SingleObject> Ptr;

    ~SingleObject()
    {
        cout << "析构函数~!~!" << endl;
    }
    //C++11 关键字delete 表民绝对禁止使用拷贝构造函数
    SingleObject(SingleObject&) = delete;
    SingleObject& operator=(const SingleObject&) = delete;
    static Ptr getInstance()
    {
        if (instance == nullptr)
        {
            //互斥锁
            lock_guard<mutex> lk(m_mutex);
            if (instance == nullptr)
            {
                instance = shared_ptr<SingleObject>(new SingleObject);
                //instance = Ptr(new SingleObject); 和上面相同
            }
        }
        return instance;
    }

private:
    SingleObject()
    {
        cout << "构造函数~!~!" << endl;
    }
    static Ptr instance;
    static mutex m_mutex;
};
//类的数据成员不能在类的声明体中初始化
//必须在类外进行初始化
SingleObject::Ptr SingleObject::instance = nullptr;
mutex SingleObject::m_mutex;


int main()
{
    SingleObject::Ptr ins = SingleObject::getInstance();
    SingleObject::Ptr ins_2 = SingleObject::getInstance();
    system("pause");
    return 0;
}

 

 3、懒汉单例--局部静态变量

 

#include<iostream>
using namespace std;

class SingleObject {
public:
    ~SingleObject()
    {
        cout << "析构函数~!~!" << endl;
    }

    //C++11 关键字delete 表民绝对禁止使用拷贝构造函数
    SingleObject(SingleObject&) = delete;
    SingleObject& operator=(const SingleObject&) = delete;

    static SingleObject& getInstance()
    {
        static SingleObject instance;
        return instance;
    }

private:
    SingleObject()
    {
        cout << "构造函数~!~!" << endl;
    }
};
//类的数据成员不能在类的声明体中初始化
//必须在类外进行初始化

int main()
{
    SingleObject& ins = SingleObject::getInstance();
    system("pause");
    return 0;
}

 

 

 

 

 

 

 

 

 

参考:https://www.cnblogs.com/sunchaothu/p/10389842.html

           https://www.cnblogs.com/sunchaothu/p/10389842.html

 

posted @ 2020-08-16 11:49  夏~  阅读(197)  评论(0编辑  收藏  举报