单例模式: 保证类只有一个实例,并且提供一个访问实例的全局访问点。
方法:
保证类只有一个实例:使构造函数是private,这样就无法顺意创建类的实例
提供一个访问实例的全局访问点:一个类的静态函数,能获取到实例。
实现代码:
1.简单版本
class singletion
{
private:
singletion(int x=1):a(x) {}
static singletion *p;
int a;
public:
int get() {return a;}
int set(int x) { a =x;}
static singletion* get_instance()
{
if (p == NULL) p = new singletion();
return p;
}
};
singletion* singletion::p=NULL;
int main()
{
singletion* p = singletion::get_instance();
cout<<p->get()<<endl;
singletion* p2 = singletion::get_instance();
p2->set(3);
cout<<p->get()<<endl;
}
class singletion
{
public:
int get() {return a;}
int set(int x) { a =x;}
static singletion* get_instance()
{
if (p == NULL) p = new singletion();
return p;
}
class garbo // 增加一个垃圾回收的内部类,作用仅是程序结束时,释放单例占用的内存
{
public:
garbo() {}
~garbo()
{
cout<<"delete p"<<endl;
delete p;
};
};
private:
singletion(int x=1):a(x) {}
static singletion *p;
int a;
static garbo _garbo;
};
singletion* singletion::p=NULL;
singletion::garbo singletion::_garbo; // 如果不执行构造,析构也不会执行
3.使用局部静态变量,不用考虑内存的释放问题,并且也实现了线程安全
class singletion2
{
private:
int a;
singletion2(int x=1):a(x) { cout<<" single2 "<<endl; }
public:
int get() {return a;}
int set(int x) { a =x;}
static singletion2* get_instance()
{
static singletion2 single;
return &single;
}
};
4.考虑线程安全
class singletion
{
public:
int get() {return a;}
int set(int x) { a =x;}
static singletion* get_instance()
{
if (p == NULL) {
lock(); // C++没有直接的Lock操作,请使用其它库的Lock,比如Boost,此处仅为了说明
if (p == NULL) p = new singletion();
unlock();
}
return p;
}
private:
singletion(int x=1):a(x) {}
static singletion *p;
int a;
};
singletion* singletion::p=NULL;
需要考虑实例的情况:
- 在类中,有一些文件锁了,文件句柄,数据库连接等等,这些随着程序的关闭而不会立即关闭的资源,必须要在程序关闭前,进行手动释放;
- 具有强迫症的程序员。