设计模式之四:单例模式

来源:互联网 发布:淘宝客服哪里培训课程 编辑:程序博客网 时间:2024/05/16 04:33

好看的排版,尽在博客园  设计模式之四:单例模式

2014-01-18 星期六 11:12:42

Singleton,继续GOF。

1、Intent

Ensure a class only has one instance, and provide a global point of access to it.

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

2、Also Known As
3、Motivation

It's important for some classes to have exactly one instance. Although there can be many printers in a system, there should be only one printer spooler. There should be only one file system and one window manager. A digital filter will have one A/D converter. An accounting system will be dedicated to serving one company.

对一些类来说,只有一个实例是很重要的。虽然系统中可以有许多打印机,但却只应该有一个打印假脱机( printer spooler) ,只应该有一个文件系统和一个窗口管理器。一个数字滤波器只能有一个A / D转换器。一个会计系统只能专用于一个公司。

How do we ensure that a class has only one instance and that the instance is easily accessible? A global variable makes an object accessible, but it doesn't keep you from instantiating multiple objects.

我们怎么样才能保证一个类只有一个实例并且这个实例易于被访问呢?一个全局变量使得一个对象可以被访问,但它不能防止你实例化多个对象。

A better solution is to make the class itself responsible for keeping track of its sole instance. The class can ensure that no other instance can be created (by intercepting requests to create new objects), and it can provide a way to access the instance. This is the Singleton pattern.

一个更好的办法是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建(通过截取创建新对象的请求) ,并且它可以提供一个访问该实例的方法。

这就是Singleton模式。

4、Applicability

Use the Singleton pattern when

●   there must be exactly one instance of a class, and it must be accessible to clients from a wellknown access point.

●   when the sole instance should be extensible by subclassing, and clients should be able to use an extended instance without modifying their code.

在下面的情况下可以使用Singleton模式

  当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。

 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

5、Structure


6、代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <iostream>
#include <memory>
#include <cstring>
#include <unistd.h>
   
#define STATIC_IN_CLASS
//实际应用中可以宏定义
///////////////// 单件模式
#define PATTERN_SINGLETON_DECLARE(classname)    \
static classname * instance();
   
#define PATTERN_SINGLETON_IMPLEMENT(classname)  \
classname * classname::instance()       \
{                                               \
    static classname * _instance = NULL;        \
    if( NULL == _instance)                      \
    {                                           \
        _instance = new classname;              \
    }                                           \
    return _instance;                           \
}                      
   
class CSingleton
{
public:
    PATTERN_SINGLETON_DECLARE(CSingleton);

#if 0
protected:
    CSingleton()    //not public
    {
        std::cout<<"CSingleton::CSingleton()"<<std::endl;
    }
#endif

public:
    ~CSingleton(){};
   
public:
    void is_singel()
    {
        std::cout<<"is_singel(),m_test = "<<m_test<<std::endl;
    }

#if 0  
    CSingleton& operator=(const CSingleton& rhs)
    {      
        if(this != &rhs)
        {
            m_test = rhs.m_test;   
        }
        std::cout<<"operator="<<std::endl;
        return *this;
    }
#endif

private:
    CSingleton(const CSingleton& rhs);
    CSingleton& operator=(const CSingleton& rhs);

private:
    int m_test;
    static CSingleton* _instance;   //按gof类图放在里面
   
    static const int t = 0;
    /*静态数据在c++中只有 static const int t = 0;
    可以初始化。
    其他都要在类的外面。 
    */
};
   
//PATTERN_SINGLETON_IMPLEMENT(CSingleton);  //ok
CSingleton* CSingleton::_instance = NULL;
CSingleton * CSingleton::instance()
{
    //lock
    if( NULL == _instance)
    {
        _instance = new CSingleton;
    }
    else
    {
        //exception
    }  
    return _instance;
}
   
#define g_CSingleton    (*CSingleton::instance())
#define g_pCSingleton   (CSingleton::instance())
   
int main(int argc, char *argv[])
{
    //只有一次输出"CSingleton::CSingleton()"
    CSingleton *ps1 = CSingleton::instance();
    ps1->is_singel();
       
    CSingleton *ps2 = g_pCSingleton;
    ps2->is_singel();
       
    CSingleton s2 = *CSingleton::instance();
    s2.is_singel();
       
    CSingleton s21 = g_CSingleton;
    s21.is_singel();
   
    sleep(1);
    (*CSingleton::instance()).is_singel();
       
    std::cout << std::endl <<"This is a Singelton Antother"<<std::endl;
    std::cout <<"Not Get By instance()"<<std::endl;
   
    #if //如果是public的话,可以编译通过。即违背了singleton
    CSingleton s3; 
    s3.m_test = 3;
       
    CSingleton s4=s3;
    s4.is_singel();
       
    s4 = *CSingleton::instance();
    s4.is_singel();
    #endif
       
    return  0;
}


7、扩展--单件注册表

A more flexible approach uses a registry of singletons. Instead of having Instancedefine the set of possible Singleton classes, the Singleton classes can register their singleton instance by name in a well-known registry.

一个更灵活的方法是使用一个单件注册表(registry of singleton ) 。可能的Singleton类的集合不是由Instance定义的, Singleton类可以根据名字在一个众所周知的注册表中注册它们的单件实例。

The registry maps between string names and singletons. When Instanceneeds a singleton, it consults the registry, asking for the singleton by name. The registry looks up the corresponding singleton (if it exists) and returns it. This approach frees Instancefrom knowing all possible Singleton classes or instances. All it requires is a common interface for all Singleton classes that includes operations for the registry:

这个注册表在字符串名字和单件之间建立映射。当 Intance需要一个单件时,它参考注册表,根据名字请求单件。注册表查询相应的单件(如果存在的话)并返回它。这个方法使得 Intance不再需要知道所有可能的 singleton类或实例。它所需要的只是所有 Singleton类的一个公共的接口,该接口包括了对注册表的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#if 1
class Singleton
{
public:
    static void Register(const char* name, Singleton*);
    static Singleton* Instance();
 
protected:
    static Singleton* Lookup(const char* name);
 
private:
    static Singleton* _instance;
    static List<NameSingletonPair>* _registry;
};
 
Singleton* Singleton::Instance ()
{
    if (_instance == 0)
    {
        const char* singletonName = getenv("SINGLETON");
        // user or environment supplies this at startup
        _instance = Lookup(singletonName);
        // Lookup returns 0 if there's no such singleton
    }
    return _instance;
}
#endif

Singleton类在何处注册它们自己?一种可能是在它们的构造器中。例如, MySingleton类可以像下面这样做:

1
2
3
4
5
MySingleton::MySingleton()
{
    // ...
    Singleton::Register("MySingleton"this);
}

0 0