设计模式学习笔记(一)——Singleton

来源:互联网 发布:大金融数据行业应用 编辑:程序博客网 时间:2024/05/21 23:00
        学习设计模式,自然从最简单的模式入手,而最简单的模式便是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所带来的问题了。程序可能还有没考虑到的方面,希望大家指正。谢谢。
原创粉丝点击