设计模式读书笔记(二) Singleton(单例)模式

来源:互联网 发布:临沂知豆出租地点 编辑:程序博客网 时间:2024/05/03 17:30

一、模式介绍

单例模式又叫做单态模式或者单件模式。在 GOF 书中给出的定义为:保证一个类仅有 一个实例,并提供一个访问它的全局访问点。单例模式中的“单例”通常用来代表那些本质上 具有唯一性的系统组件(或者叫做资源)。比如文件系统、资源管理器等等。

二、模式的目的

单利模式的目的就是为了控制特定的类的数量,比如在一个pc上只允许有一个鼠标指针在运动,再比如操作系统只能有一个窗口管理器,一般来说这个类是属于一种静态的资源,它并不需要有多个实例的存在(当然,也可以根据实际情况来调整这个数量,比如同一个ps4最多只能允许4个控制器接入一样)

三、实现

单例模式可以说的上是用的最多的模式之一,那么我们该怎么去实现这个模式呢?其实很简单,在C++里面甚至声明一个全局的static变量也能做到,不过这样肯定是不够优雅的做法。我们下面来看看实现的代码:

#include <iostream>using namespace std;class CSingleton{private:    ~CSingleton()    {        cout << "exit" << endl;    }    CSingleton() :min(0)    {        cout << "get" << endl;    }    CSingleton(const CSingleton &);    CSingleton & operator = (const CSingleton &);    static CSingleton* m_Instance;public:    static CSingleton* GetInstance()    {        if(m_Instance == NULL)            m_Instance = new CSingleton();        return m_Instance;    }    void speak()    {        min++;        cout << min << endl;    }};int main(){    CSingleton::GetInstance()->speak();    getchar();}

我们可以看到,上面的代码中,将构造函数,赋值构造函数等声明成了private,这样是为了防止外界进行实例化,同时该类提供了一个GetInstance()函数来进行对该实例对象的一个访问。在GetInstance()里面判断对象是否被实例化了,如果实例化了则返回对象,这是用了懒惰式的构建方法。

单例类CSingleton有以下特征:

  • 它有一个指向唯一实例的静态指针m_pInstance,并且是私有的;
  • 它有一个公有的函数,可以获取这个唯一的实例,并且在需要的时候创建该实例;
  • 它的构造函数是私有的,这样就不能从别处创建该类的实例。

不过大家可以观察到上面的代码,会存在一个隐患:m_Instance指向的对象何时会被释放,当然你可以在调用的最后,使用GetInstance()获取该对象,然后delete,不过这样的话会比较依赖使用的人的记忆力,万一忘了,就造成了内存泄漏了。所以一个比较合适的方法就是让这个单例类自己管理自己的释放!

这里有好多的实现的方式:比如加一个内嵌类去管理等等。下面我们会给出一个比较简单的方式来实现:

#include <iostream>using namespace std;class CSingleton{private:    ~CSingleton()    {        cout << "exit" << endl;    }    CSingleton() :min(0)    {        cout << "get" << endl;    }    CSingleton(const CSingleton &);    CSingleton & operator = (const CSingleton &);    int min;public:    static CSingleton* GetInstance()    {        static CSingleton instance;        return &instance;    }    void speak()    {        min++;        cout << min << endl;    }};int main(){    CSingleton::GetInstance()->speak();    getchar();}

通过将Instance声明成一个局部的static变量,同时不声明成指针,调用的时候返回它的引用以免导致调用复制构造函数出错,这样在销毁的时候它就会自己调用自己的析构函数~~妈妈再也不怕我忘记释放资源了~

1 0