剑指offer——面试题2实现Singleton模式
题目:设计一个类,我们只能生成该类的一个实例
单例模式
一种设计模式,设计一个类,保证这个类只有一个对象实例
应用场合:如windows中只能有一个任务管理器,同时间内一个系统只能有一个计时工具
要点:一、某个类只能由一个实例 (只提供私有构造函数)
二、必须自行创建这个实例 (类定义中含有一个该类的静态私有对象)
三、必须自行访问这个实例 (该类提供了一个静态的公有函数用于创建或获取它本身的静态私有对象)
单例模式的优点:1、在内存中只有一个对象,节省内存空间
2、避免频繁的创建销毁对象,可以提高性能
3、避免对共享资源的多重占用
4、可以访问全局
单例模式的适用范围:1、需要频繁实例化然后销毁的对象
2、创建对象耗时或资源过多,但又常用的对象
3、有状态的工具类对象
4、频繁访问数据库或文件的对象
5、要求只有一个对象的场景
单例模式分为懒汉模式(可能会有线程安全)和饿汉模式
单例模式
该种模式下,将只会输出创建,析构函数将不会被调用,
因为类内创建指针,存放的是地址变量,而实际的实例对象在堆区,通过New得到,
因此调用析构时候只是释放了指针资源,而没有释放堆区内存
饿汉模式:在类产生的时候即创建对象,直达程序结束才释放,
因此该实例对象需要存储在内存的全局数据区,因此用static修饰
饿汉模式是线程安全的,不需要考虑线程同步
#include <iostream>
using namespace std;
class Single
{
private:
Single(){cout <<"creat"<<endl;}//构造和析构都设为是私有函数
Single(const Single&){} //设置拷贝构造为私有,防止通过拷贝构造赋值给它
Single &operator = (const Single &); //防止通过直接赋值给值
~Single()
{
cout<<"destroy"<<endl;
// delete Instance;
//Instance = NULL;
} //析构函数正常时,指针无法释放堆内存储
static Single *Instance; //单例对象指针
//另一种不需要单独手动释放的方法是,将Instance这里不定义为指针,
//而是直接声明对象,在getInstance返回值时候返回地址
public:
static Single * getInstance() //获取单例对象的接口必须是公共的
{
return Instance;
}
/* 如果希望释放堆内空间,需要添加如下代码:
static void releaseInstance()
{
delete Instance; //如果该位置delete,则析构中就不能delete了
cout<<"release"<<endl;
}
*/
/*或者定义一个内部类,在内部类销毁时顺便会释放堆区资源
private:
class Inner
{
Inner (){};
~Inner()
{
if(Instance != NULL)
{
delete Instance;
Instance = NULL;
}
}
};
*/
};
Single* Single::Instance = new Single(); //静态成员的赋值,饿汉模式在全局一开始就给分配空间
/*
懒汉模式:第一次调用getInstance时候才创建实例
懒汉模式是线程不安全的,因为多线程时要考虑getInstance的线程同步
*/
class CSingleton
{
private:
CSingleton(){cout<<"creat"<<endl;}
CSingleton(const CSingleton&);
CSingleton& operator=(const CSingleton &);
~CSingleton(){cout<<"destroy"<<endl;}
public:
static CSingleton *getInstance()
{
lock(); //用于线程同步加锁
static CSingleton myInstance;
unlock(); //用于线程同步解锁
return &myInstance;
/*
或者
//lock(); //线程同步,互斥锁
if(myInstance == NULL)
myInstance = new CSingleton();
return myInstance; //然后再在全局给myInstance赋值NULL.手动释放或内部类释放
//unlock(); //线程同步,互斥锁解锁
*/
}
};
测试主函数如下:
int main()
{
Single *sin1 = Single::getInstance();
Single *sin2 = Single::getInstance();
Single *sin3 = Single::getInstance();
CSingleton *csin1 = CSingleton::getInstance();
CSingleton *csin2 = CSingleton::getInstance();
CSingleton *csin3 = CSingleton::getInstance();
//Single::releaseInstance();
return 0;
}