单例模式
单例模式:是一种常见的设计模式,在它的核心结构中值有一个被称为单例的类,一个类只有一个实例,即一个类只被创建了一次。
一:单例模式都是使用静态方法创建的,所以单例对象在内存中静态共享区中存储
原因:
- a、首先为了禁止其他的程序创建该类,所以该类的构造函数私有化。
- b、在本类中自定义一个对象(禁止程序创建该类,就要自己创建一个供使用,否则不能叫做单例)
- c、提供一个可访问类自定义对象的方法,对外提供该对象的访问方法
类中方法被调用的形式:创建类的对象调用方法,直接用类名调用;在类名直接调用的过程中,类中方法必须是静态的,然而静态方法不能访问非静态成员变量。所以该类中自定义变量必须是静态的。
单例模式分类:懒汉模式和饿汉模式 ;
第1种:懒汉模式(线程不安全)
public class Singleton {
private static Singleton instance;
private Singleton(){}
public static Singleton getInstance(){
if (instance == null){
instance = new Singleton();
}
return instance;
}
}
第2种:懒汉模式(线程安全)
public class Singleton {
private static Singleton instance;
private Singleton(){}
/**
* 在方法中添加synchronized关键词,能够在多线程中很好的工作,
* 但是由于synchronized锁机制,效率低
* @return
*/
public static synchronized Singleton getInstance(){
if (instance == null){
instance = new Singleton();
}
return instance;
}
}
第3种:饿汉模式
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton(){}
/**
* 在类加载过程中就直接实例,加载时候慢,但使用时候比较快
* @return
*/
public static synchronized Singleton getInstance(){
return instance;
}
}
第4种:饿汉(变种)
public class Singleton {
private static Singleton instance = null;
static {
instance = new Singleton();
}
private Singleton(){}
/**
* 在类加载过程中就直接实例,加载时候慢,但使用时候比较快
* @return
*/
public static synchronized Singleton getInstance(){
return instance;
}
}
第5种:静态内部类
public class Singleton {
private static class SingletonHolder{
private static final Singleton instance = new Singleton();
}
private Singleton(){}
/**
* 这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程,
* 它跟第三种和第四种方式不同的是(很细微的差别):
* 第三种和第四种方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),
* 而这种方式是Singleton类被装载了,instance不一定被初始化。
* 因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,
* 才会显示装载SingletonHolder类,从而实例化instance。想象一下,如果实例化instance很消耗资源,
* 我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,
* 因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,
* 那么这个时候实例化instance显然是不合适的。这个时候,这种方式相比第三和第四种方法就显得更合理
* @return
*/
public static final Singleton getInstance(){
return SingletonHolder.instance;
}
}
第6种:枚举(基本上不常见)
public enum Singleton {
instance;
public void getInstance(){
}
}