单例模式
# 分类
创建型模式
# 定义
单例模式(Singleton Pattern) 是几个创建型模式中最独立的一个,它的主要特点不是根据客户程序调用生成一个新的实例,而是控制某个类型的实例数量是唯一一个。
# 意图
单例模式的意图就是要保证一个类只有一个实例
,并提供一个访问它的全局访问点
。
# 应用场景
- 创建一个对象需要消耗的资源过多,比如I/O与数据库的连接等。
应用案例
- WEB中的计数器,不用每次刷新都在数据库里加一次,但单例先缓冲起来。
- 要求生产唯一序列号。
- 一个班级只有一个班主任。
- 日志管理器。
- 一些设备管理器常常设计为单例模式。比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。
# 角色与结构图
- Singleton:
单例角色
保证只有一个实例和唯一的全局访问点。
下图解释了单例模式中各角色的作用

# 示例代码
//单线程版本
public class Singleton
{
// 唯一实例
private static Singleton instance;
// 封闭客户程序的直接实例化
protected Singleton() { }
public static Singleton Instance
{
get
{
if (instance == null)
instance=new Singleton();
return instance;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//多线程版本
public class Singleton
{
protected Singleton() { }
private static volatile Singleton instance=null;
/// Lazy方式创建唯一实例的过程
public static Singleton Instance()
{
if (instance == null) // 外层if
lock (typeof(Singleton)) // 多线程中共享资源同步
if (instance == null) // 内层if
instance=new Singleton();
return instance;
}
}
多线程同步:在多线程环境中,volatile 用于保证一个线程对某个变量的修改可以被其他线程立即看到。
虽然它并不是一种同步机制(如 mutex 或 lock),
但它保证了对该变量的写操作不会被线程缓存,
确保了多线程环境下变量的一致性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 优点
- 在内存中只有一个实例,
减少了内存的开销
,尤其是频繁的创建和销毁实例
。(比如管理学院首页页面缓存) - 避免对资源的多重占用。(比如些文件操作)
# 缺点
- 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外部怎样来实例化。
# 小结
- 实际上单例模式要做的就是通过控制类型实例的创建,确保后续使用的都是之前创建好的一个实例,通过这样的一个封装,客户程序就无须知道该类型实现的内部细节。其中的参与者就只有Singleton自己,它的职责是定义一个 Instance 操作(类成员或类方法、类属性),作为客户程序访问 Singleton 的一个,而且是唯一的一个实例。
- 主要解决?一个全局使用的类频繁地创建与销毁。
- 何时使用?当您想控制实例数目,节省系统资源的时候。
- 如何解决?判断系统是否已经有这个单例,如果有则返回,如果没有则创建。
- 关键代码?构造函数是私有的。
- 注意:多线程时要加锁。
# 大结
动机:在软件系统中,经常有这样一些特殊的类,必须保证它们在系统只存在一个实例,才能确保它们的逻辑正确性,以及良好的效率。 这应该是类设计者的责任,而不是使用者的责任。
# 一句话概括
某个类只能有一个实例,并且只提供一个全局访问点。
编辑 (opens new window)
上次更新: 2025/03/22, 13:47:44