开发中我们知道,我们能够使用一个全局变量让一个对象能够被访问,但它不能防止实例化多个对象。一个最好的办法就是让类自身负责保存它的唯一实例,这个类应该保证没有其他实例可以被创建,并且它应该提供一个访问该实例的方法。单例模式就是这样一种保证类对应仅有一个实例,并提供访问它的统一全局访问点的设计模式。
以Java语言为例,单例模式最简单的实现方法就是将构造函数设置为private
访问权限,这样用户就不能new
该对象了,用户只能通过我们提供的getInstance()
方法初始化对象,方法内部会根据单例模式的要求按需new
出对象。
用户获取时初始化全局唯一的实例,这种单例模式称为懒汉式。
public class Student {
private static Student student;
private Student() {
Student.student = new Student();
}
public Student getInstance() {
return student;
}
}
程序刚运行时实例就立即生成产生,这种单例模式称为饿汉式。
public class Student {
private static Student student = new Student();
private Student() {
}
public Student getInstance() {
return student;
}
}
以上述代码为例,我们先不考虑用户获取student
实例后多线程操作它是否有问题,仅仅观察单例模式的两种实现,它是否仍有线程安全问题?
实际上,上面代码的懒汉式仍就不是线程安全的,因为多个线程同时调用getInstance()
时可能造成创建多个student
实例,这可能造成一些混乱!因此多线程情况下,懒汉式的单例模式应该使用线程同步,而饿汉式单例模式不存在这个问题。
懒汉式的实例按需加载但是可能造成线程安全问题,这种方式启动快,但是首次调用getInstance()
方法时慢。饿汉式的实例程序启动时就加载,实现上不会有线程安全问题,但启动可能较慢。具体使用哪一种,应该根据程序的需求来选择合适的实现。