返回
Featured image of post 设计模式 —— 单件模式

设计模式 —— 单件模式

单件模式——独一无二的对象

初看起来好像很简单,实际接触后,发现并不是这么一回事。先给自己几个问题:

  • 创建对象的时候,如何知道现在只有一个?
  • 如何保证创建对象时候的原子性?(不能保证就有可能创建多于 1 个的对象)
  • 如何获取/访问这个唯一对象?

1. 基础概念

  • 定义/意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
  • 原理:让类自身保存它的唯一实例,并提供一个访问该实例的方法。实例的唯一性由类来保证。
  • 类图:
  • 出场嘉宾
    • Singleton:单件类。
      • 定义一个接口,允许客户访问唯一实例。此接口是一个类操作。
      • 负责创建唯一实例。

2. 解决什么问题?如何解决?

  • 系统中,有些东西只需要一份就够了,因此要保证只有一份。
  • 解决方法:只允许创建一个。但如何保证只有一个呢,见其他部分。

3. 优缺点是什么?

3.1 优点

  • 对唯一实例的创建是受控的——不允许直接创建(new 或变量)。
  • 对唯一实例的访问是受控的。
  • 缩小命名空间。
    • 此模式是对全局变量的一种改进。
    • 避免了存储唯一实例的全局变量污染命名空间。
    • (同一命名空间内,两个名字相同,就会冲突。)
  • 允许对操作和表示的精化。【?!】
    • 单件类可以有子类。
    • 可以使用所需的拓展类运行时配置应用。
  • 允许可变的数目的实例。
  • 比类操作更灵活。
    • 如果使用类操作(C++ 的静态成员函数、Smalltalk 的类方法)的方式来封装单件功能,会使得改变设计以允许多个实例变得困难。
  • 惰性 (lazy) 初始化,惰性创建——不需要的时候,不会创建。

3.2 缺点

4. 使用场景是什么?

  • 多个模块共用的全局数据库/配置。

5. 注意

  • 保证一个唯一的实例。
  • C++ 实现注意:如果将单件定义为一个全局或静态的对象,然后依赖自动的初始化,是不够的,原因:
    • 不能保证静态对象只有一个实例会被声明。
    • 可能没有足够的信息初始化实例。(可能需要在运行时获取信息)
    • C++ 没有定义转换单元(Translation unit)上全局对象的构造器的调用顺序。【?!】
    • 无论是否使用,都会被创建。(一开始就创建了)

6. 应用实例?

w. 待办

x. 疑问

  • 如何拓展单件类?
  • 5. 注意里面第 2 点第 3 个原因,不理解!
  • 单件注册表
  • 《设计模式:可复用面向对象软件的基础》里面好像没有考虑线程安全?

y. 拓展

z. 参考

相信美好的事情即将发生。
Built with Hugo
Theme Stack designed by Jimmy