学习设计模式,自然从最简单的模式入手,而最简单的模式便是Singleton。所以第一篇就来所以说Singleton。看完GOF和Design patterns in Java的书,感觉Singleton虽然简单,但是想写出一个好的Singleton也不是一上来就能写出来的。
Singleton的用处自然是保证一个类只有一个唯一的实例。在建模中涉及到的只能有一个对象,例如Struts中的Action类就是一例。除此之外,Singleton还使得该对象只有一个全局访问点。这就是SIngleton的作用。
说得比较抽象,我们来看一个简单Singleton的C++和Java的代码:
C++:
类定义:
class Singleton
{
public:
static Singleton * Instance();
~Singleton();

private:
Singleton();

static Singleton * instance;
};
方法实现:
Singleton * Singleton::instance = 0;

Singleton::Singleton()
{

}

Singleton::~Singleton()
{

}

Singleton * Singleton::Instance()
{
if (instance == 0) {
instance = new Singleton();
}

return instance;
}
Java:
public class Singleton {
private static Singleton instance;
public static Singleton getInstance() {
if (instance == null)
instance = new Singleton();
return instance;
}
/** Creates a new instance of Singleton */
private Singleton() {
}
}
通过上面的例子可以看出,Singleton的实现并不难,只要将构造函数访问域设为私有,然后添加一个静态引用和一个获得该应用的静态方法即可。其实在C++中定义一个全局静态变量也可以达到这个效果,但是像Java这样的语言就是能使用Singleton了。
上面的程序有一个问题,就是只能运行在单线程的环境下。为此我在C++上作了个实验。首先#include <windows.h>。在SIngleton::Instance()函数中增加一个Sleep(1000),程序如下:
Singleton * Singleton::Instance()
{
if (instance == 0) {
Sleep(1000);
instance = new Singleton();
}

return instance;
}
然后在主函数中创建两个线程,程序如下:
static Singleton * s1 = 0, * s2 = 0;

DWORD WINAPI ThreadProc1(PVOID)
{
s1 = Singleton::Instance();

return 0;
}

DWORD WINAPI ThreadProc2(PVOID)
{
s2 = Singleton::Instance();

return 0;
}

int main(int argc, char* argv[])
{
DWORD threadID1;
DWORD threadID2;

CreateThread(NULL, 0, ThreadProc1, NULL, 0, &threadID1);
CreateThread(NULL, 0, ThreadProc2, NULL, 0, &threadID2);

Sleep(10000);

std::cout << s1 << " " << s2;

return 0;
}
这样修改后在运行程序,打印出来的s1和s2地址就不是同一个地址了。结果如下:
00372D68 00372E68Press any key to continue
可见当在多线程环境下使用这个Singleton就会出现创建不止一个实力的情况,所以我们需要给Singleton加锁。请看下面的代码。
C++:
class Singleton
{
public:
static Singleton * Instance();
virtual ~Singleton();

private:
Singleton();

static CMutex mutex;
static Singleton * instance;
};
Singleton * Singleton::instance = 0;
CMutex Singleton::mutex;

Singleton::Singleton()
{

}

Singleton::~Singleton()
{

}

Singleton * Singleton::Instance()
{
mutex.Lock();

if (instance == 0) {
Sleep(1000);
instance = new Singleton();
}

mutex.Unlock();

return instance;
}
此外需要#include <afxmt.h>,并且在项目设置中要设置动态链接MFC库。
Java:
public class Singleton {
private static Singleton instance;
private static Object lock = Singleton.class;
public static Singleton getInstance() {
synchronized (lock) {
if (instance == null)
instance = new Singleton();
return instance;
}
}
/** Creates a new instance of Singleton */
private Singleton() {
}
}
运用加锁就可以解决在多线程环境下使用Singleton所带来的问题了。程序可能还有没考虑到的方面,希望大家指正。谢谢。
Singleton的用处自然是保证一个类只有一个唯一的实例。在建模中涉及到的只能有一个对象,例如Struts中的Action类就是一例。除此之外,Singleton还使得该对象只有一个全局访问点。这就是SIngleton的作用。
说得比较抽象,我们来看一个简单Singleton的C++和Java的代码:
C++:
类定义:














































上面的程序有一个问题,就是只能运行在单线程的环境下。为此我在C++上作了个实验。首先#include <windows.h>。在SIngleton::Instance()函数中增加一个Sleep(1000),程序如下:







































00372D68 00372E68Press any key to continue
可见当在多线程环境下使用这个Singleton就会出现创建不止一个实力的情况,所以我们需要给Singleton加锁。请看下面的代码。
C++:






































Java:

















