学习设计模式,自然从最简单的模式入手,而最简单的模式便是Singleton。所以***篇就来所以说Singleton模式。看完GOF和Design patterns in Java的书,感觉Singleton虽然简单,但是想写出一个好的Singleton也不是一上来就能写出来的。
Singleton模式的用处自然是保证一个类只有一个***的实例。在建模中涉及到的只能有一个对象,例如Struts中的Action类就是一例。除此之外,Singleton还使得该对象只有一个全局访问点。这就是SIngleton的作用。
说得比较抽象,我们来看一个简单Singleton的C++和Java的代码:
C++ Singleton模式:
类定义:
- 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 Singleton模式:
- 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
- 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地址就不是同一个地址了。结果如下:
0372D68 00372E68Press any key to continue
可见当在多线程环境下使用这个Singleton就会出现创建不止一个实力的情况,所以我们需要给Singleton加锁。请看下面的代码。
C++ Singleton模式:
- 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>,
Java Singleton模式:
- 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模式所带来的问题了。
【编辑推荐】