单例模式(Singleton) -- 对象创建型模式

意图

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

适用性

  • 当类只能有一个实例并且客户可以从一个从所周知的访问点访问它。
  • 当这个唯一实例应该通过子类来实现可扩展性,并且用户不需要修改代码就可以使用一个扩展的实例。

结构

Singleton

  • Singleton
    定义一个Instance操作,允许客户访问它的唯一实例。C++中通常是一个静态成员函数。
    可能负责创建它自己的唯一实例。

协作

客户只能通过Singleton的Instance操作访问一个Singleton的实例。

效果

  • 对唯一实例的访问控制。
    因为Singletion类封装了它的唯一实例,并且客户只能通过Instance接口访问,所以它可以严格控制客户怎样及何时访问它。
  • 缩小命名空间污染。
    Singleton是对全局变量的一种改进,它避免了那些存储唯一实例的全局变量污染命名空间。
  • 允许对操作和表示的精化。
    Singleton类可以有子类,而且用这个扩展类的实例来配置一个应用是很容易的。你可以用你所需类的实例在运行时配置应用。
  • 允许可变数目的实例。
    这个模式可以使你方便改变想法,允许通过改变实现来控制应用可以使用的实例的数目。
  • 比类操作更为灵活。
    另一种封装Singleton功能的方式使用类操作(即C++中静态成员函数)。但这会使得难以改变设计以允许一个类有多个实例,C++中静态成员函数不是虚函数,子类不能多态重定义他们。

实现

1) 保证唯一的实例。C++通常将创建实例的操作隐藏在一个类函数后面,它保证只有一个实例被创建。并且需要隐藏构造器来防止客户通过其他方式能创建多个实例。

class Singleton {
public:
    static Singleton* Instance();
protected:
    Singleton();
private:
    static Singleton* m_instance = 0;
};

Singleton* Singleton::m_instance = 0;
Singleton* Singleton::Instance() {
    if (m_instance == 0) {
        m_instance = new Singleton;
    }
    return m_instance;
}

2) 创建Singleton类的子类。指向实例的变量可以用子类的实例来初始化,这样可以创建不同的对象。最简单的技术是在Singleton的Instance操作中决定你要使用哪个单例。
另一个选择是将Instance的实现从父类中分离出来并放入子类。这样允许C++程序员在连接时刻决定单例的类(即通过链入一个包含不同实现的对象文件),但对客户则隐藏了这一点。
一个更灵活的方法是使用一个单例注册表。Singleton类可以根据名字在一个众所周知的注册表中注册它们的单件实例。
这个注册表在字符串名字和单件之间建立映射。当Instance需要一个单件时,它参考注册表,根据名字请求单件。
注册表查询相应的单件(如果存在的化)并返回它。这个方法使得Instance不再需要知道所有的Singleton类或实例。它需要知道的只有所有Singleton类的一个公共接口,该接口包括了对注册表的操作。

class Singleton {
public:
    static void Register(const char* name, Singleton*);
    static Singleton* Instance();
protected:
    static Singleton* Lookup(const char* name);
private:
    static Singleton* m_instance;
    static List<NameSingletonPair>* m_registry;
};

Register以给定名字注册Singleton实例,Lookup操作根据给定名字查找单例。

示例

// 只生成一个实例的工厂类
class MazeFactory {
public:
    static MazeFactory* Instance();
    // ...
protected:
    MazeFactory();
private:
    static MazeFactory* m_instance;
};

MazeFactory* MazeFactory::m_instance = 0;
MazeFactory* MazeFactory::Instance() {
    if (m_instance == 0) {
        m_instance = new MazeFactory;
    }
    return m_instance;
}

// 多个子类的情况
MazeFactory* MazeFactory::Instance() {
    if (m_instance == 0) {
        const char* mazeStyle = getenv("MAZESTYLE");
        if (strcmp(mazeStyle, "bombed") == 0){
            m_instance = new BombedMazeFactory;
        } else if (strcmp(mazeStyle, "enchanted") {
            m_instance = new EnchantedMazeFactory;
        }
        //... other possible subclass
        else {  // default
            m_instance = new MazeFactory;
        }
    }
    return m_instance;
}

相关模式

很多模式可以使用Singleton模式来实现,比如Abstract Factory、Builder、Prototype。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值