单例模式:
一种设计模式,它的目的是确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。它适用于需要全局唯一的对象或资源的情况。
23种设计模式种最简单最常见的一种(高频考点) 要求:通过一个类只能创建一个对象
1.构造函数私有化
2.定义静态的成员函数,其调用只能通过类名进行调用。
可以看到其地址一样,这就达到了我们要的效果
第一种写法:
引用+静态(将创建的单一对象放到全局静态区)(不推荐)
#include <iostream>
using std::cout;
using std::endl;
//单例模式的实现方式一:不推荐使用
class Point{
public:
//实现了构造函数私有,即不可通过外部去创建对象
//因为只有对象才能调用成员函数,故将该函数设计为静态函数
//使其只能通过类名::进行调用
static Point &getInstance()
{
//我们用引用的话,因为Point pt(1,2)是一个临时变量
//其生命周期随着函数的消失而消失
//故我们用static将其定义为全局静态对象即可返回引用
/* static Point pt(1,2); */
static Point pt;
return pt;
}
void init(int x,int y)
{
_ix=x;
_iy=y;
}
void print()
{
cout<<"("<<_ix
<<","<<_iy
<<")"<<endl;
}
//私有化之后的构造函数只能在类内调用
private:
Point(int ix=0 ,int iy=0)
: _ix(ix)
,_iy(iy)
{
cout<<"Point(int,int)"<<endl;
}
int _ix;
int _iy;
};
//全局对象也不能创建
/* Point pt3(1,3); */
void test(){
//该对象不可能是一个栈对象
/* Point pt1(1,2);//创建无数个对象 */
/* Point pt2(3,4);//在语法上不能编译通过 */
Point &pt = Point::getInstance();
Point &pt2 = Point::getInstance();
Point &pt3 = Point::getInstance();
cout<<"pt:"<<&pt<<endl;
cout<<"pt2:"<<&pt2<<endl;
cout<<"pt3:"<<&pt3<<endl;
pt.print();
pt2.print();
}
int main()
{
test();
return 0;
}
第二种方式:
第一次调用getInstance函数时,直接new表达式创建堆对象
后续的调用直接返回第一次创建的对象即可
第二种写法是静态指针+静态数据成员(返回指针地址)
代码:
#include <iostream>
using std::cout;
using std::endl;
//单例模式的实现方式二:推荐使用
class Point{
public:
//第一次调用getInstance函数时,直接new表达式创建堆对象
//后续的调用直接返回第一次创建的对象即可
static Point *getInstance()
{
if(_pInstance == nullptr)
{
_pInstance = new Point;
}
return _pInstance;
}
static void destory()
{
if(_pInstance)
{
delete _pInstance;
_pInstance = nullptr;
}
}
void init(int x,int y)
{
_ix=x;
_iy=y;
}
void print()
{
cout<<"("<<_ix
<<","<<_iy
<<")"<<endl;
}
private:
Point(int ix=0 ,int iy=0)
: _ix(ix)
,_iy(iy)
{
cout<<"Point(int,int)"<<endl;
}
~Point()
{
cout<<"~Point()"<<endl;
}
//私有化之后的构造函数只能在类内调用
private:
int _ix;
int _iy;
static Point *_pInstance;
};
//在全局静态区进行初始化
Point * Point::_pInstance = nullptr;
//全局对象也不能创建
/* Point pt3(1,3); */
void test(){
//该对象不可能是一个栈对象
/* Point pt1(1,2);//创建无数个对象 */
/* Point pt2(3,4);//在语法上不能编译通过 */
Point *pt = Point::getInstance();
Point *pt2 = Point::getInstance();
cout<<"pt:"<<pt<<endl;
cout<<"pt2:"<<pt2<<endl;
pt->print();
pt2->print();
//不能让该表达式编译通过
/* delete pt; */
/* delete pt2; //功能上可以实现,但是在代码形式上显得很突兀,不够优雅 */
Point::destory();//完成对空间的回收
}
int main()
{
test();
return 0;
}
具体步骤:
-
在类中定义一个静态的指向本类型的指针 (该指针用来存储第一次调用静态成员函数getInstance创建出来的对象)
-
将构造函数私有化(不能在类之外直接调用)
-
在public区域,定义一个静态成员函数 (第一次调用该函数时,在该函数中new一个对象,后续的调用都是直接返回第一次创建的对象。)
应用场景:
-
单例模式可以用来替换全局对象类型
-
配置文件中的信息可以存储在单例对象中
-
网页库,倒排索引库都可以使用单例模式