设计模式之禅——单例模式

引:如果每个人可以走的路只有一条,如果每个人想要的东西都是一个(单例模式),那么人应该都不会迷茫了吧。虽然解决了迷茫,但是也抹杀了多样性,有好有坏,各有所见。

定义

确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。——创造类

下面是它的通用类图:
singleton

代码实现有两种,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 饿汉式单例 线程安全

public class Singleton {
private static final Singleton = new Singleton();
// 限制产生多个对象
private Singleton() { ... }
// 通过该方法获得实例对象
public static Singleton getSingleton() {
return singleton;
}
// 类中其他方法尽量是static
public static void doSomething { ... }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 懒汉式单例 线程不安全

public class Singleton {
private static final Singleton = null;
// 限制产生多个对象
private Singleton() { ... }
// 通过该方法获得实例对象
public static Singleton getSingleton() {
if (singleton = null) {
singleton = new Singleton();
}
return singleton;
}
// 类中其他方法尽量是static
public static void doSomething { ... }
}

应用

优点

  1. 减少内存开支
  2. 减少系统的性能开销
  3. 避免对资源的多重占用

缺点

  1. 扩展困难,由于它需要自行实例化
  2. 不利于测试,由于单例没完成,不能测试
  3. 单一职责有冲突

使用场景

  1. 要求生成唯一序列号的环境
  2. 在整个项目中需要一个共享访问带你或共享数据
  3. 创建一个对象需要消耗的资源过多,如访问IO和数据库
  4. 需要定义大量的静态常量和静态方法(如工具类)的环境

注意事项

  1. 在高并发的情况下,请注意单例模式的线程同步问题,选择合适的实现模式。
  2. 不可以复制,即不实现Cloneable接口。

最佳实践

在Spring中,每个Bean默认就是单例的,这样的优点是Spring容器可以管理这些Bean的生命周期,决定什么时候销魂,销毁的时候要如何处理,等等。如果采用非单例模式,则Bean初始化后的管理交由J2EE容器,Spring容器不在跟踪管理Bean的生命周期。