2009年6月1日 星期一

Singleton in windows modules

Singleton應該是GOF書中的Design Pattern中,最常被使用的Pattern之一。

而在實做上,有許多不同的變化。為了彰顯此次的主題,採用最簡單的方法來表示(Meyer's Singleton)。


class Singleton {

private:
Singleton() { cout << "Constructor" << endl; }
~Singleton() { cout << "Destructor" << endl; }
public:
static Singleton& GetSingleton() {
static Singleton ms_singleton;
return ms_singleton;
}
void Func() { cout << "Func invoked" << endl; }
};

主程式的部份︰

#include "Singleton.h"
int main()
{
Singleton::GetSingleton().Func();
return 0;
}


結果應該是︰
Constructor
Func invoked
Destructor
一切看起來都很美好。

不過當程式逐漸複雜化,需要將程式切成幾個Modules之後(Dynamic Linking Library、非Static Linking Library),事情有了微妙的變化。
我們在Dynamic Linking Library輸出一個Function,他的實做就是
void Func()
{

Singleton::GetSingleton().Func();
}


我們的主程式改寫成這樣
int main()
{
Singleton::GetSingleton().Func();
Func();
return 0;
}

以下是執行結果︰
Constructor
Func invoked
Constructor
Func invoked
Destructor
Destructor
這結果跟Singleton的定義背道而馳,Singleton的原則就是只有一個實體。

會造成這樣的原因是,由於Modules都能看到完整的Singleton的implementation,在Modules之間並不知道已經有某個 Module已經建立了Singleton,於是在自己的Module間重新建立一個Singleton,於是就造成這種現象。

對於這個問題,微軟也提供了一套解決方案,就是統一使用某Module的Singleton。
#ifdef SINGLETON_EXPORTS
    #define _DLLExport __declspec(dllexport)
#else
    #define _DLLExport __declspec(dllimport)
#endif
class Singleton {
private:
Singleton() { cout << "Constructor" << endl; }
~Singleton() { cout << "Destructor" << endl; }
public:
static _DLLExport Singleton& GetSingleton() {
static Singleton ms_singleton;
return ms_singleton;
}
void Func() { cout << "Func invoked" << endl; }
};

然後在提供Singleton Object的Module中加入 MARCO SINGLETON_EXPORTS,一切大功告成。

結果就如我們所預期了。
Constructor
Func invoked
Func invoked
Destructor

我果然走清新、健康、專業路線啊。

沒有留言:

張貼留言

 

我們搬家了

新部落格在http://b-plurkers.com/