【转】设计模式学习笔记(5)-单例

单例模式在实际编程中经常遇到,用起来十分简单,是所有创建型模式中最容易理解的。单例模式,顾名思义,即一个类在程序运行时只产生一个对象。

有人会问,既然这个类只产生一个对象,那何不将这个类中的所有方法和属性都声明成静态的呢?对于面向对象编程来说,使用静态的方法往往并不是一个良好的设计,静态对象在JVM初始化后就驻留内存,不能被垃圾收集器收集;不便于管理和存储等。单例模式其实就是存储在类中的一个静态属性中,我们之所以不在全局静态变量中存储因为全局变量会对程序的命名空间造成污染,同时也不利于对对象的访问进行控制。
单例模式所要解决的问题主要是:如何确保只有一个实例。

我们知道对象的创建要经过构造函数,并且通常构造函数是公有(public)的。如果将构造函数声明为私有的呢?那么外部就无法直接调用构造函数来生成对象。这样,我们可以通过类中的一个委托函数取得对象,该函数可以通过某些控制使得全局只有一个对象,这是十分容易做到的。

这样我们就有一个设想:

Singleton类中有一个静态属性instance,它存储的是一个Singleton对象指针,构造函数是protected或private权限。类必须提供一个public权限的函数以取得instance对象指针。

代码示例是十分简单的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Singleton
{
private:
    Singleton(){}
    static Singleton* instance;
public:
    static Singleton* getInstance();
};
Singleton* Singleton::instance = 0;
Singleton* Singleton::getInstance()
{
    if (Singleton::instance == 0)
    {
        Singleton::instance = new Singleton();
    }
    return instance;
}
int main(int argc, const char *argv[])
{
    Singleton* single = Singleton::getInstance();
    return 0;
}

注意,我们这里在getInstance方法中实例化了instance,当然你也可以直接这样写:

1
Singleton* Singleton::instance = new Singleton();

这样一来,在程序运行时instance就实例化了,而第一种方法则在第一次使用instance对象才实例化,这又叫惰性(lazy)初始化。

由于C++的特殊性,我们可以利用友元函数来将Singleton类中的静态成员分离出来,这样使得Singleton类保持纯粹性(由于别的语言没有这一特性,故不常用)。

GoF书中还提到了单例模式的子类问题。由于静态成员函数不能被子类继承,所以无法利用多态的特性。这种情况主要采用两种方案:单例注册表和环境变量。个人人为不太重要,因此没有介绍。

最后看看单例模式的适用性:

  • 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时
  • 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时

单例模式的重点不在于如何实现,而在于什么时候该使用单例。一般常用的如资源独占,包括文件访问、数据库访问、端口、进程控制等等,使用单例模式可有效解决访问冲突等问题。

 

原文链接:http://lecoding.com/articles/142.html

posted on 2013-03-05 14:03  TheKingOfKingFish  阅读(120)  评论(0)    收藏  举报

导航