单例用的就比较多并且广了,说的是 某个单例类,只在内存中创建唯一一个实例,比如android中application,只有一个实例,只初始化一次,又比如window的资源管理器,不管你开多少个,永远只有一个在运行。好处是节省资源,尤其是对于频繁访问的类。
要写单例模式,我认为最重要的是什么时候实例化这个类,有以下几种可以:
1.类初始化就产生实例
2.在方法里面写,类初始化实例化,在调用方法才实例化
那么单例的创建方式有4中(其实是5种,只不过有一种因为不推荐使用,就不学习了),这种写法分类来自尚学堂的老师。
饿汉法:
这个写法是类在初始化就已经完成单例的创建的,不可以延迟操作
package SinglePattern;
/**
* 这是类初始化就马上加载,恶汉
* @author cloudhuan
*
*/
public class SinglePattern02 {
//这里类初始化都是线程安全的
private static final SinglePattern02 PATTERN02 = new SinglePattern02();
private SinglePattern02(){};
public static SinglePattern02 getInstance(){
return PATTERN02;
}
}
懒汉法:
这个可以实现延迟加载,但是对于多线程来说效率是最低的,因为有一个synchronized 同步锁,创建过程可能会等待。
package SinglePattern;
/**
* 这个可以延迟加载,真正使用的时候才去加载,懒汉
* 类加载都是线程安全的,但是这里需要加同步锁
* @author cloudhuan
*
*/
public class SingleInstance01 {
public static SingleInstance01 singleInstance;
//可能有多个方法去用,所以要同步,不加可能还是会造成多个对象
public static synchronized SingleInstance01 getInstance(){
if(singleInstance == null){
return new SingleInstance01();
}
return singleInstance;
}
public void printHello(){
System.out.println("hello");
}
}
静态内部类法:
是最推荐的写法,把实例化放在静态内部类里面,在有需要才会加载内部类,并且类初始化是天然同步的。
package SinglePattern;
/**
* 静态内部类的加载方式,用的最多的,集合懒汉和恶汉的优点
* 1.类加载是天然线程安全的
* 2.用到才加载
* @author cloudhuan
*
*/
public class SinglePattern03 {
private static class SingleInst{
private static SinglePattern03 pattern03 = new SinglePattern03();
}
private SinglePattern03(){}
public static SinglePattern03 getInstance(){
return SingleInst.pattern03;
}
}
枚举法:
当不需要延迟加载就用这个吧,因为枚举类型是系统自带的单例模式,没有什么BUG,写法也是超级简单的
package SinglePattern;
/**
* 这是通过枚举方式的,枚举的类型就是系统自带的单例模式
* @author cloudhuan
*
*/
public enum SinglePattern04 {
INSTANCE("aaa");
SinglePattern04(String str){
System.out.println(str);
}
}
上面四种方式,推荐的是枚举和静态内部类模式,效率最高。