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