跳转至

单例模式

分类:创建型模式。

类结构

classDiagram
    direction TB
    class Client
    class Singleton {
        -Singleton instance$
        -Singleton()
        +getInstance() Singleton$
        +operation()
    }
    Client ..> Singleton : 获取并使用实例

角色定义

角色 定义
Singleton(单例) 控制自身实例的创建,并提供统一访问点。图中构造器私有,instance 和 getInstance() 是静态成员;具体实现还需根据运行环境处理并发初始化。
Client(客户) 通过 getInstance() 获取实例,再调用其业务操作。

Head First 示例:共享巧克力锅炉状态

《Head First 设计模式》第 5 章用巧克力锅炉说明统一实例入口的作用:锅炉只有在空置时才能填充,只有装有尚未煮沸的混合物时才能加热,只有煮沸后才能排出。作者 2020 年第二版配套代码 singleton/chocolate 用 empty 与 boiled 两个布尔字段表示这些状态,让 ChocolateController 通过 ChocolateBoiler.getInstance() 获取操作对象。

该目录采用惰性初始化:构造器私有,静态字段 uniqueInstance 初始为空,第一次请求时才创建实例。它没有同步措施;示例入口展示的是顺序调用下复用同一实例的过程,不能据此声称实现了线程安全。

具体类名 对应角色 职责
ChocolateBoiler 单例及业务状态持有者 通过私有构造器和静态入口管理实例,依据 empty、boiled 控制填充、加热、排出。
ChocolateController 客户与示例入口 在 main() 中取得锅炉、操作它,再次请求实例。

示例 UML

图中包含该目录的两个类,省略方法内的条件分支与输出语句。- 表示私有成员,$ 标记静态字段或方法;控制器只在 main() 的局部变量中保存锅炉引用,因此画为使用依赖。

classDiagram
    direction TB
    class ChocolateController {
        +main(String[] args) void$
    }
    class ChocolateBoiler {
        -boolean empty
        -boolean boiled
        -ChocolateBoiler uniqueInstance$
        -ChocolateBoiler()
        +getInstance() ChocolateBoiler$
        +fill() void
        +boil() void
        +drain() void
        +isEmpty() boolean
        +isBoiled() boolean
    }
    ChocolateController ..> ChocolateBoiler : 获取实例并操作锅炉

协作过程

  1. ChocolateController.main() 首次调用 getInstance()。如果 uniqueInstance 为空,就执行私有构造器,将 empty 设为 true、boiled 设为 false,保存并返回新实例。
  2. 控制器调用 fill()。锅炉为空时,方法将 empty 改为 false,并将 boiled 设为 false,表示装入一批尚未煮沸的混合物。
  3. boil() 仅在锅炉非空且尚未煮沸时把 boiled 改为 true。
  4. drain() 仅在锅炉非空且已煮沸时把 empty 改为 true。源码此时没有重置 boiled;下一次成功调用 fill() 才会将它重新设为 false。
  5. 入口再次调用 getInstance(),顺序执行时取得已有实例。这个示例的初始化和状态操作都没有同步:并发首次访问可能创建多个对象,业务状态检查与修改也可能交错,因此其适用说明必须保留这一限制。

固定版本源码:

评论