单例模式大概是讲到设计模式被提及的最多的设计模式。
单例模式被大家说到的最多的特点就在于其在一个进程中只允许一个类创建一个对象(该类在内存中只占用一份内存)。这的确是单例模式所体现出来的,这样的特点在于一些为了防止冲突的场景下具有十分重要的意义,比如,某些资源只允许被创建一次,不允许存在多次的操作,像端口、文件、数据库等。
单例模式的实现要点在于将构造函数私有化,从而不能正常的通过构造函数来创建一个对象或者通过构造函数返回对象指针。
在失去了常规的返回指针的方式之后,将返回对象指针的途径设置在get成员函数中,但是没有对象,怎么能够访问成员函数呢?方法就是通过静态成员函数。静态成员函数的特点其实可以看成是一个全局的函数,但是其具有访问该类的私有成员函数(前面提到的私有化之后的构造函数)的权限。也就是说,现在针对一个类,通过一个具有特权的全局函数和一个特殊的全局变量—类的静态变量,来管理该类的所有创建过程,控制该类的构造函数,控制构造函数仅仅被执行一次,实现仅创建一个对象的目的。
下面是实现单例模式的代码:
#include <iostream>
class singleton
{
public:
static singleton* getInstance(void);
private:
singleton(void);
static singleton* ptr;
};
singleton* singleton::getInstance(void)
{
if(NULL == ptr)
{
ptr = new singleton();
}
return ptr;
}
singleton::singleton(void)
{
//////就是一个正常的,普通的构造函数
}
singleton* singleton::ptr = NULL;
void main(void)
{
singleton* p = singleton::getInstance();
std::cout<<p<<std::endl;
singleton *p2 = singleton::getInstance();
std::cout<<p2<<std::endl;
std::system("pause");
}
但是,通过下面能够看到,单例模式也存在一个问题,那就是没有析构函数,内存只被申请,却不被回收,肯定是会成为一个大问题的。那么,能否仿照获取对象的方法,来仿写一个回收空间的函数呢?
答案是肯定的。
写一个静态函数,对静态变量指针判断,满足析构条件就进行调用私有的析构函数,如果已经为空指针了,那就不掉用私有的析构函数。
void singleton::deleteObj(void)
{
if (NULL != ptr)
{
delete ptr;
ptr = NULL;
}
}
下面是运行的结构,但是我们运行了exe四次:
通过上面的截图能够看到,其实在不同的进程下,还是生成了不同的内存地址的对象,这如果反映到实际的情况下面,应该就是不同进程在抢占同一个端口,这也就说明,其实,单例模式并不能解决资源抢占的问题。