定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
1.饿汉式
//饿汉模式
//这种方式在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。
// 这种方式基于类加载机制避免了多线程的同步问题,但是也不能确定有其他的方式(或者其他的静态方法)
// 导致类装载,这时候初始化instance显然没有达到懒加载的效果
public class Singleton_ehan {
private static Singleton_ehan singletonEhan = new Singleton_ehan();
private Singleton_ehan(){ }
public static Singleton_ehan getSingletonEhan(){
return singletonEhan;
}
}
2.懒汉模式
//懒汉模式申明了一个静态对象,在用户第一次调用时初始化,虽然节约了资源,但第一次加载时需要实例化,
// 反映稍慢一些,而且在多线程不能正常工作
public class Singleton_lanhan {
private static Singleton_lanhan singletonLanhan;
private Singleton_lanhan(){}
//线程不安全
public static Singleton_lanhan getInstance(){
if (singletonLanhan == null){
singletonLanhan = new Singleton_lanhan();
}
return singletonLanhan;
}
//线程安全
public synchronized static Singleton_lanhan getInstance1(){
if (singletonLanhan == null){
singletonLanhan = new Singleton_lanhan();
}
return singletonLanhan;
}
//双重检查模式
public static Singleton_lanhan getInstance2(){
if (singletonLanhan == null){
synchronized (Singleton_lanhan.class){
if (singletonLanhan == null){
singletonLanhan = new Singleton_lanhan();
}
}
}
return singletonLanhan;
}
}
3.静态内部类实现
//第一次加载Singleton类时并不会初始化sInstance,只有第一次调用getInstance方法时
// 虚拟机加载SingletonHolder 并初始化sInstance ,这样不仅能确保线程安全也能保证
// Singleton类的唯一性,所以推荐使用静态内部类单例模式
//静态内部类
public class Singleton_InnerClass {
private Singleton_InnerClass(){
}
public static Singleton_InnerClass getInstance(){
return Holder.singleton_innerClass;
}
private static class Holder{
private static final Singleton_InnerClass singleton_innerClass = new Singleton_InnerClass();
}
//防止反序列化时 重新创建对象
private Object readResolve() throws ObjectStreamException {
return Holder.singleton_innerClass;
}
}
4.单例管理器
//用SingletonManager 将多种的单例类统一管理,在使用时根据key获取对象对应类型的对象。
// 这种方式使得我们可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,
// 降低了用户的使用成本,也对用户隐藏了具体实现,降低了耦合度。
public class SingletonManager {
private static Map<String,Object> map = new HashMap<>();
public void registerSingleton(String name,Object singleton){
if (map != null){
map.put(name,singleton);
}
}
public Object getSingleton(String name){
if (map != null){
return map.get(name);
}
return null;
}
}