单例模式(C++描述)+可以创建任何类的单例模式(template)
一.单例模式总结:
假设公司只有一台打印机,学校只有一个校长,多个线程处理同一个文件,我们在new对象时,想要避免这些只有一个的变量出现多个,此时就需要用到单例模式。
用法总结:
1.只能通过调用类中的函数来创建对象,其他方法均不行。
2.实例化的对象必须是唯一的,如果还有用户申请返回对象,返回的对象其实是同一个实例化的对象。
优点:
1.防止堆资源被浪费,降低了内存空间的开销;
2.作为唯一的公共资源防止被同时使用。
二.关于单例模式的问题:
1.构造函数与析构函数为什么要放在private区域中?
这样就只能通过getInstance和destory两个函数来操纵构造和析构函数!
2.getInstance为什么要加上static?
因为要想用类名直接调用成员函数,成员函数必须是static修饰的才行!
3.pInstance为什么要用static修饰?
因为操作pInstance的getInstance函数是用static修饰的,所以pInstance也只能加上staic修饰(static函数只能操作static成员变量!)
4.为什么在类外还要对pInstance进行定义?
因为在类中pInstance只是进行了申明,光是申明无法进行操作,必须加上定义才行!
1.懒汉模式(lazy loading)
Singleton *Singleton::pInstance = NULL;这个语句表明了是懒汉模式,即pInstance没有在一开始就申请对象。这样是线程不安全的状态(因为可能多个线程同时申请对象),则需要加锁。
class Singleton
{
public:
//函数这里为什么要加上static?因为要想用类名直接调用成员函数,成员函数必须是static修饰的才行!
static Singleton *getInstance()
{
if (pInstance == NULL)
{
//如果还没有进行实例化,那么可以创建唯一的实例,自己调用private中的构造函数
pInstance = new Singleton();
return pInstance;
}
else
{
//如果已经进行了实例化,那么就直接返回已经再全局静态区创建的实例即可
return pInstance;
}
}
static void destory()
{
//防止double delete
if (pInstance)
{
delete pInstance;
pInstance = NULL;
}
}
private:
//将构造函数与析构函数都进行私有化,这样便不能直接实例化类
Singleton() {}
~Singleton() {}
static Singleton *pInstance; //这里必须用static修饰的原因是因为getInstance函数也是static修饰的
};
Singleton *Singleton::pInstance = NULL;
int main(){
Singleton *p1 = Singleton::getInstance();
p1->print();
//指针对象的destory应该与NULL连起来,不然之后p1仍能够使用,会发生错误!
p1->destory();
p1 = NULL;
p1->a = 5;
cout << p1->a << endl;
return 0;
}
2.饿汉模式
Singleton* Singleton::_pInstance = new Singleton();说明了这个是饿汉模式,需要在类加载的时候就申请对象,这样的话就是线程安全的状态。
#include <iostream>
using std::cout;
using std::endl;
class Singleton{
public:
static Singleton* getInstance()
{
return _pInstance;
}
static void destory(){
if (_pInstance){
delete _pInstance;
_pInstance = NULL;
}
}
private:
Singleton(){ cout << "Singleton()" << endl;}
~Singleton(){cout << "~Singleton()" << endl;}
static Singleton* _pInstance;
};
//Singleton* Singleton::_pInstance = NULL;//这是懒汉模式,线程不安全
Singleton* Singleton::_pInstance = new Singleton();//这是饿汉模式,线程安全
int main(){
Singleton* p1 = Singleton::getInstance();
Singleton* p2 = Singleton::getInstance();
cout << p1 << endl;
cout << p2 << endl;
p1->destory();
p2->destory();
return 0;
}
template+单例模式:可以创建任何类的单例
问题:实现一个模板形式的单例类,要求对于任意类型的类经过Singleton的处理之后,都能获取一个单例对象,并且可以传递任意参数。
Point pt(1, 2);
Point pt2(3, 4);
Computer com("Mac", 8888);
int main(void)
{
Computer * p1 = Singleton<Computer>::getInstance("Xiaomi", 6666);
Computer * p2 = Singleton<Computer>::getInstance("Xiaomi", 6666);
Point * p3 = Singleton<Point>::getInstance(1, 2);
Point * p4 = Singleton<Point>::getInstance(1, 2);
return 0;
}
思路:Singleton类中真正起着作用的是_pInstance这个指针,只需要将指针类型转换为模板型即可。
Singleton.h:
#ifndef _MY_QUEUE_H_
#define _MY_QUEUE_H_
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
namespace wd
{
class Point{
public:
template<typename... Args>
Point(Args... args){}
~Point(){}
};
class Computer{
public:
template<typename... Args>
Computer(Args... args){}
~Computer(){}
};
template<class T>
class Singleton{
public:
template<typename... Args>
static T* getInstance(Args... args){
if (!_pInstance){
_pInstance = new T(args...);
}
return _pInstance;
}
static void destory(){
if (_pInstance){
delete _pInstance;
_pInstance = NULL;
}
}
private:
Singleton(){}
~Singleton(){}
static T* _pInstance;
};
template<class T>
T* Singleton<T>::_pInstance = NULL;//懒汉模式
} //end of namespace wd
#endif
main.cpp:
#include "Singleton.h"
using namespace wd;
//多参数测试
void test0(){
Computer c1("ASUS", 6666);
Computer c2("Mac", 9999);
Point p1(3,4);
Point p2 ("sdf", 'a');
}
//单例测试
void test1(){
Computer *c1 = Singleton<Computer>::getInstance("ASUS", 6666);
Computer *c2 = Singleton<Computer>::getInstance("ASUS", 6666);
cout << c1 << endl;
cout << c2 << endl;
//Singleton<Computer>::destory();
Point *p1 = Singleton<Point>::getInstance(1,2);
Point *p2 = Singleton<Point>::getInstance("dfas",'as');
cout << p1 << endl;
cout << p2 << endl;
Singleton<Point>::destory();
}
int main()
{
test1();
return 0;
}
本文深入探讨C++中的单例模式,包括懒汉模式和饿汉模式的实现及线程安全性讨论。并通过模板方式实现了通用的单例模式,适用于任何类的单例创建。
762

被折叠的 条评论
为什么被折叠?



