1. 为什么要单例模式?
在对象需要获取全局变量时,我们需要用到单例模式,单例模式也是解决获取全局变量的重要方法之一。
2. 单 例模式的原理
单例模式,通过私有化构造函数来达到不给外界实例化对象,之后再由该对象提供一个静态公有接口创建这个对象,该接口并对该对象是否已创建判断,再取决是否创建对象,达到一个全局唯一的效果。之后就通过该接口就可以对该对象的类内公有成员进行访问了。
3.简单实现
#include <iostream>
using namespace std;
class A
{
private:
a(); //构造函数是私有的,这样就不能在其它地方创建该实例
static A *p; //定义一个唯一指向实例的静态指针,并且是私有的。
static int b;
public:
static A* instance() //定义一个公有函数,可以获取这个唯一的实例,并且在需要时创建该实例。
{
if(p == NULL) //判断是否第一次调用
p = new A;
return p;
}
static void show()
{
cout << b << endl;
}
};
int A::b=1; //static定义的数据成员必须在类外初始化,因为它是整个类的一部分,而不是属于某个对象。
only* A::p=NULL;
说明:
可以看出,实现一个简单的单例模式,主要分为三个步骤:
1.私有化构造函数,使其不可以没直接被外部实例化。
2.在其类内公有成员区做一个创建类的方法。
其本质是外部由于不可访问类的私有区,所以通过类自己的公有去访问创建私有区的构造函数,从而创建类。之后对该方法做全局唯一的限制,就可以保证全局只创建一次对象。
3.类外部定义指向该对象的指针。
4.饿汉单例模式
// 单例类
class A {
public:
// 获取此类的 唯一静态实例
static A & getInstance() {
return instance;
}
// 公有函数部分
void func1() {
cout << "1" << endl;
}
private:
// 私有化 默认构造函数 拷贝构造函数 析构函数
// 即 禁止对 class singleton 的类外构造和拷贝
A() {
// 构造部分
};
A(A &b) {
// 此函数无用 因为已经私有化
// 相当于禁止了拷贝构造
};
~A() {
// 析构部分
};
static A instance;
};
//使用方法
int main(int argc, char *argv[]) {
// 由于私有化了 默认构造函数 以及 拷贝构造函数
// 所以只可以用引用方式 获取到单例类的实例
A &c = A::getInstance();
A.func1();
system("pause");
return 0;
}
饿汉模型通过static在程序刚刚开始执行的时候就对对象进行实例化了。这样做的结果是更快的初始化对象,缺点是资源浪费。
5.懒汉模式
class A
{
private:
static A* m_instance;
A(){}
public:
static A* getInstance();
};
A* A::getInstance()
{
if(NULL == m_instance)
{
Lock();//借用其它类来实现,如boost
if(NULL == m_instance)
{
m_instance = new Singleton;
}
UnLock();
}
return m_instance;
}
懒汉模式写法如下,只有在使用的时候才实例化对象。缺点就是慢。
这里使用一个完整的例子。
class sun :public son
{
public:
~sun() {std::cout << "sun::~sun()";}
public:
static sun * GetInstance();
private:
sun(int a, int b, int c, double m, int d);
static sun * m_instance;
};
#include"instance.h"
sun * sun::m_instance(NULL);
sun::sun(int a, int b, int c, double m, int d) :son(a, b, c, m, d)
{
std::cout << "sun::sun"<<endl;
}
sun * sun::GetInstance()
{
if (NULL == m_instance)
{
m_instance = new sun(5,6,7,8.2,10);
}
return m_instance;
}
//然后主函数如下:
#include"instance.h"
//#include"instancetest.h"
using namespace::std;
int main()
{
sun * test = sun::GetInstance();
return 0;
}
*本文为学习笔记,如有不对,或有高见的欢迎留言。