一、单例模式的基本定义
一个类有且仅有一个实例,并且提供了一个全局的访问点
二、单例模式适用场景:
1.面试被问到的几率较高
2.需要频繁的实例化然后销毁对象
3.创建对象时耗时或者消耗资源过多,但又经常用到的对象
4.有状态的工具对象
5.频繁访问数据库或者文件的对象
6.资源共享情况下,避免资源操作时导致性能损耗
7.控制资源的情况下,方便资源之间的互相通信,如线程池
三、单例模式的特点:
1.只能有一个实例
2.单例必须是自己来创建自己的唯一实例
3.单例必须给其他使用者提供接口
四、实现单例模式:
根据单例模式的特点,创建一个单例模式的实例。
public class SingletonDemo {
/**
* 因为只能有一个实例,所以不能允许随便new
*/
private SingletonDemo() {
}
/**
* 因为构造方法是私有的,所以需要定义静态变量,防止可以直接被其他类调用,定义为私有的
*/
private static SingletonDemo singletonInstance = null;
/**
* 其他类使用实例时只能通过静态方法获取
*
* @return
*/
public static SingletonDemo getSingletonInstance() {
if(singletonInstance==null){
singletonInstance = new SingletonDemo();
}
return singletonInstance;
}
}
以上的单例模式是根据单例模式特点最容易想到的一种实现方式,如果此单例一直没有被用到,则一直不会初始化,对资源浪费较少,但是缺点是非线程安全的。面试的时候一般不推荐写这种。
线程安全可以定义singletonInstance熟悉时直接new一个对象,这样就是线程安全的。静态变量是在加载类的时候初始化的,所以获取单例实例的时候就可以直接获取。但是缺点是每次加载类的时候都会初始化,如果用不到单例实例,就会对资源造成一定的浪费。但是这种实现方式容易记录,可以面试的时候捎带上这种实现方式。
public class SingletonDemo {
/**
* 因为只能有一个实例,所以不能允许随便new
*/
private SingletonDemo() {
}
/**
* 因为构造方法是私有的,所以需要定义静态变量,防止可以直接被其他类调用,定义为私有的
*/
private static SingletonDemo singletonInstance = new SingletonDemo();
/**
* 其他类使用实例时只能通过静态方法获取
*
* @return
*/
public static SingletonDemo getSingletonInstance() {
return singletonInstance;
}
}
如果比较在意资源的优化(不使用不初始化),同样线程安全除了加载时初始化也可以使用 synchronized关键字来保证线程安全 ,这样可以保证不使用不出初始化,但是缺点是效率较低,大多数情况下是不需要同步的,但是加了synchronized每次调用都会加锁。
public class SingletonDemo {
/**
* 因为只能有一个实例,所以不能允许随便new
*/
private SingletonDemo() {
}
/**
* 因为构造方法是私有的,所以需要定义静态变量,防止可以直接被其他类调用,定义为私有的
*/
private static SingletonDemo singletonInstance = null;
/**
* 其他类使用实例时只能通过静态方法获取
*
* @return
*/
public static synchronized SingletonDemo getSingletonInstance() {
if(singletonInstance==null){
singletonInstance = new SingletonDemo();
}
return singletonInstance;
}
}
针对以上实现方式,可以继续优化使用效率。synchronized除了可以修饰方法以外还可以修饰代码块,因为同步使用的时候只是在初始化的时候需要同步,可以双重校验的方式对以上实现方式加强。
public class SingletonDemo {
/**
* 因为只能有一个实例,所以不能允许随便new
*/
private SingletonDemo() {
}
/**
* 因为构造方法是私有的,所以需要定义静态变量,防止可以直接被其他类调用,定义为私有的
*/
private static SingletonDemo singletonInstance = null;
/**
* 其他类使用实例时只能通过静态方法获取
*
* @return
*/
public static SingletonDemo getSingletonInstance() {
//只有singletonInstance为空的时候使用synchronized
if(singletonInstance==null){
synchronized (SingletonDemo.class){
//再次校验singletonInstance是否为空
if(singletonInstance==null){
singletonInstance = new SingletonDemo();
}
}
}
return singletonInstance;
}
}