写好的代码就是为了以后少写一些代码。
单件模式就是为了实现在一个应用程序中保证只有一个类的实例在运行。在一个应用程序中用到多个单件类的话,其实也不需要实现好多遍。下面是C++和C#实现的泛型的单件模式示例代码。注意:在ConcreteSingleton中Operation函数中操作的资源要实现线程安全,自己添加保护措施。
C++代码:
// locker.h
#pragma once
#include <windows.h>
namespace hangba
{
namespace designpattern
{
class Locker
{
public:
Locker();
virtual ~Locker();
void Lock();
void Unlock();
private:
CRITICAL_SECTION m_cs;
};
}
}
// locker.cpp
#include "stdafx.h"
#include "Locker.h"
using namespace hangba::designpattern;
Locker::Locker()
{
InitializeCriticalSection(&m_cs);
}
Locker::~Locker()
{
DeleteCriticalSection(&m_cs);
}
void Locker::Lock()
{
EnterCriticalSection(&m_cs);
}
void Locker::Unlock()
{
LeaveCriticalSection(&m_cs);
}
// singleton.h
#pragma once
#include <memory>
#include "Locker.h"
using namespace std;
namespace hangba
{
namespace designpattern
{
template<typename T>
class Singleton
{
public:
static T* GetInstance()
{
if (m_pInstance.get() == nullptr)
{
m_locker.Lock();
if (m_pInstance.get() == nullptr)
{
m_pInstance.reset(new T);
}
m_locker.Unlock();
}
return m_pInstance.get();
}
private:
Singleton(const Singleton&)
{
}
Singleton& operator=(const Singleton&)
{
}
Singleton()
{
}
virtual ~Singleton()
{
}
private:
friend class auto_ptr<T>;
static auto_ptr<T> m_pInstance;
static Locker m_locker;
};
template<typename T>
auto_ptr<T> Singleton<T>::m_pInstance;
template<typename T>
Locker Singleton<T>::m_locker;
#define DECLARE_SINGLTON_CLASS(T) \
friend class auto_ptr<T>; \
friend class Singleton<T>;
}
}
// ConcreteSingleton.h
#pragma once
#include "../hangba/designpattern/Singleton.h"
using namespace hangba::designpattern;
#include <iostream>
using namespace std;
class ConcreteSingleton
{
public:
void Operation()
{
cout << "ConcreteSingleton's operation()" << endl;
}
DECLARE_SINGLTON_CLASS(ConcreteSingleton);
private:
ConcreteSingleton();
virtual ~ConcreteSingleton();
};
typedef Singleton<ConcreteSingleton> CONCRETE_SINGLETON;
// ConcreteSingleton.cpp
#include "stdafx.h"
#include "ConcreteSingleton.h"
ConcreteSingleton::ConcreteSingleton()
{
}
ConcreteSingleton::~ConcreteSingleton()
{
}
// 单件模式.cpp
// 单件模式.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "ConcreteSingleton.h"
int _tmain(int argc, _TCHAR* argv[])
{
// 用法一
ConcreteSingleton* p1 = Singleton<ConcreteSingleton>::GetInstance();
p1->Operation();
// 用法二
ConcreteSingleton* p2 = CONCRETE_SINGLETON::GetInstance();
p2->Operation();
// 用法三
CONCRETE_SINGLETON::GetInstance()->Operation();
// 测试p1和p2
if (p1 == p2)
{
cout << "单件模式获取到的数据是相同的" << endl;
}
else
{
cout << "单件模式获取到的数据是不相同的" << endl;
}
getchar();
return 0;
}
C#代码:
/*
* 由SharpDevelop创建。
* 用户: hangba
* 日期: 2016/3/7
* 时间: 10:39
*
* 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
*/
using System;
namespace 单件模式
{
/// <summary>
/// Description of SingletonException.
/// </summary>
public sealed class SingletonException : Exception
{
public SingletonException(string message) : base(message)
{
}
}
}
/*
* 由SharpDevelop创建。
* 用户: hangba
* 日期: 2016/3/7
* 时间: 10:22
*
* 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
namespace 单件模式
{
/// <summary>
/// Description of Singleton.
/// </summary>
public class Singleton<T> where T : class
{
private static readonly object locker = new object();
private static T instance;
public static T Instance
{
get
{
if (instance == null)
{
lock(locker)
{
if (instance == null)
{
ConstructorInfo ci = typeof(T).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[0], null);
if (ci == null)
{
throw new SingletonException("allocate T failed.");
}
instance = (T)ci.Invoke(null);
}
}
}
return instance;
}
}
}
}
/*
* 由SharpDevelop创建。
* 用户: hangba
* 日期: 2016/3/7
* 时间: 10:48
*
* 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
*/
using System;
namespace 单件模式
{
/// <summary>
/// Description of ConcreteSingleton.
/// </summary>
public class ConcreteSingleton
{
public void Operation()
{
System.Console.WriteLine("ConcreteSingleton's Operation.");
}
private ConcreteSingleton()
{
}
public static ConcreteSingleton Instance
{
get
{
return Singleton<ConcreteSingleton>.Instance;
}
}
}
}
/*
* 由SharpDevelop创建。
* 用户: hangba
* 日期: 2016/3/7
* 时间: 10:22
*
* 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
*/
using System;
namespace 单件模式
{
class Program
{
public static void Main(string[] args)
{
// 使用方法
try
{
ConcreteSingleton.Instance.Operation();
}
catch (SingletonException e)
{
System.Console.WriteLine(e.Message);
}
// 比较测试
try
{
ConcreteSingleton cs1 = ConcreteSingleton.Instance;
ConcreteSingleton cs2 = ConcreteSingleton.Instance;
if (cs1 == cs2)
{
System.Console.WriteLine("多个线程获取到的实例是一样的。");
}
else
{
System.Console.WriteLine("多个线程获取到的实例是不一样的。");
}
}
catch (SingletonException e)
{
System.Console.WriteLine(e.Message);
}
// TODO: Implement Functionality Here
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}