1、项目需求
假设,有一个项目中,各个分系统都需要完成存盘的功能,而且需要存在一个文件中,此时,各分系统的程序员不需要关心存盘功能是如何实现的,而是共同调用一个方法来实现该功能。
2、项目实现-全局变量
首先定义一个存盘类,具有打印需要存的数据的功能。
//FileRecord.h
#pragma once
#include <iostream>
using namespace std;
class FileRecord
{
public:
FileRecord(void);
~FileRecord(void);
int num;
void start(int );
};
//FileRecord.cpp
#include "StdAfx.h"
#include "FileRecord.h"
FileRecord::FileRecord(void)
{
num = 0;
}
FileRecord::~FileRecord(void)
{
}
void FileRecord::start(int name)
{
while(num<50){
num++;
if(name == 1){
printf("1 start in file->%d\n",num);
}
else{
printf("2 start in file->%d\n",num);
}
}
}
其中,可以分别用两个实例去调用start函数,通过观察打印的num值,确定是否为单例。
// SingleTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include "FileRecord.h"
using namespace std;
FileRecord g_fileRecord;//创建的全局变量
DWORD WINAPI Fun1(LPVOID lpParamter)
{
FileRecord* m_file = (FileRecord*)lpParamter;
m_file->start(1);
return 0L;
}
DWORD WINAPI Fun2(LPVOID lpParamter)
{
FileRecord* m_file = (FileRecord*)lpParamter;
m_file->start(2);
return 0L;
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hThread1 = CreateThread(NULL, 0, Fun1, &g_fileRecord, NULL, NULL);
HANDLE hThread2 = CreateThread(NULL, 0, Fun2, &g_fileRecord, NULL, NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
int instring;
cin>>instring;
return 0;
}
打印结果可以看出,两个线程访问,的确是单例。
但是,一方面,全局变量可以被任何地方访问到,不够安全;另一方面,在团队协作开发时,别人的项目还需要考虑你是不是定义了全局变量吗?
因此,当别人需要使用到单例时,首先想的并不是你有没有创建,而是自己需要的时候创建一下用即可的思路。
2、项目实现-懒汉式
参考教程例子:
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
可以把原来的类改成:
//FileRecord.h
#pragma once
#include <iostream>
using namespace std;
class FileRecord
{
private:
FileRecord(void);
~FileRecord(void);
int num;
static FileRecord *instance;
public:
static FileRecord* getInstance();
void start(int );
};
//FileRecord.cpp
#include "StdAfx.h"
#include "FileRecord.h"
FileRecord * FileRecord::instance = NULL;
FileRecord::FileRecord(void)
{
num = 0;
}
FileRecord::~FileRecord(void)
{
}
FileRecord *FileRecord::getInstance()
{
if (instance == NULL) {
instance = new FileRecord();
}
return instance;
}
void FileRecord::start(int name)
{
while(num<50){
num++;
if(name == 1){
printf("1 start in file->%d\n",num);
}
else{
printf("2 start in file->%d\n",num);
}
}
}
如上,虽然可以实现单例模式,但是是线程不安全的,当多个线程创建时,容易出问题。另外,对于该单例类的资源释放不太好处理。
我们可以进一步处理:
FileRecord *FileRecord::getInstance()
{
/*if (instance == NULL) {
instance = new FileRecord();
}
return instance;*/
static FileRecord obj;
return &obj;
}
2、项目实现-饿汉式
FileRecord * FileRecord::instance = new FileRecord();
FileRecord *FileRecord::getInstance()
{
/*if (instance == NULL) {
instance = new FileRecord();
}
return instance;*/
//static FileRecord obj;
return instance;
}