单件模式——独一无二的对象
初看起来好像很简单,实际接触后,发现并不是这么一回事。先给自己几个问题:
- 创建对象的时候,如何知道现在只有一个?
- 如何保证创建对象时候的原子性?(不能保证就有可能创建多于 1 个的对象)
- 如何获取/访问这个唯一对象?
1. 基础概念
- 定义/意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
- 原理:让类自身保存它的唯一实例,并提供一个访问该实例的方法。实例的唯一性由类来保证。
- 类图:
- 出场嘉宾
- Singleton:单件类。
- 定义一个接口,允许客户访问唯一实例。此接口是一个类操作。
- 负责创建唯一实例。
- Singleton:单件类。
2. 解决什么问题?如何解决?
- 系统中,有些东西只需要一份就够了,因此要保证只有一份。
- 解决方法:只允许创建一个。但如何保证只有一个呢,见其他部分。
3. 优缺点是什么?
3.1 优点
- 对唯一实例的创建是受控的——不允许直接创建(new 或变量)。
- 对唯一实例的访问是受控的。
- 缩小命名空间。
- 此模式是对全局变量的一种改进。
- 避免了存储唯一实例的全局变量污染命名空间。
- (同一命名空间内,两个名字相同,就会冲突。)
- 允许对操作和表示的精化。【?!】
单件类
可以有子类。- 可以使用所
需的拓展类
在运行时
配置应用。
- 允许可变的数目的实例。
- 比类操作更灵活。
- 如果使用类操作(C++ 的静态成员函数、Smalltalk 的类方法)的方式来封装单件功能,会使得改变设计以允许多个实例变得困难。
- 惰性 (lazy) 初始化,惰性创建——不需要的时候,不会创建。
3.2 缺点
4. 使用场景是什么?
- 多个模块共用的全局数据库/配置。
5. 注意
- 保证一个唯一的实例。
- C++ 实现注意:如果将单件定义为一个全局或静态的对象,然后依赖自动的初始化,是不够的,原因:
- 不能保证静态对象只有一个实例会被声明。
- 可能没有足够的信息初始化实例。(可能需要在运行时获取信息)
- C++ 没有定义转换单元(Translation unit)上全局对象的构造器的调用顺序。【?!】
- 无论是否使用,都会被创建。(一开始就创建了)
6. 应用实例?
w. 待办
x. 疑问
- 如何拓展单件类?
5. 注意
里面第 2 点第 3 个原因,不理解!单件注册表
?- 《设计模式:可复用面向对象软件的基础》里面好像没有考虑线程安全?