您的当前位置:首页正文

6种常见的单例模式

2024-12-10 来源:伴沃教育

1.饿汉式

类加载的时候就会初始化,他是线程安全的,但是类加载的时候就初始化这样会预先消耗一部分资源。

/**
 * Created by lijiayi on 2017/3/1.
 * 饿汉式单例
 */
public class Singleton {
    //生成单例对象
    private static final Singleton mSingleton = new Singleton();

    //私有化构造方法
    private Singleton() {
    }

    //获取单例对象
    public static Singleton getInstance() {
        return mSingleton;
    }
}



2.懒汉式

当第一次使用的时候才创建对象,合理占用资源,但是当该对象已经创建的时候,调用getInstance()方法会产生不必要的开销,这是懒汉式的一个缺点。

/**
 * Created by lijiayi on 2017/3/1.
 * 懒汉式单例
 */
public class Singleton {
    //声明单例对象
    private static Singleton mSingleton;

    //私有化构造方法
    private Singleton() {
    }

    //同步该方法获取单例对象
    public static synchronized Singleton getInstance() {
        //当该对象为空的时候创建该对象
        if (mSingleton == null) {
            mSingleton = new Singleton();
        }
        //返回该对象实例
        return mSingleton;
    }
}


3.DCL式

该方式能保证在需要的时候才初始化单例,又能够保证线程安全,而且单例初始化后调用getInstance()不会进行同步锁。

/**
 * Created by lijiayi on 2017/3/1.
 * DCL单例
 */
public class Singleton {
    //声明单例对象
    private static Singleton mSingleton;

    //私有化构造方法
    private Singleton() {
    }

    //同步该方法获取单例对象
    public static synchronized Singleton getInstance() {
        //当该对象为空的时候先同步这个对象
        if (mSingleton == null) {
            synchronized (Singleton.class) {
                //再判断是否为空
                if (mSingleton == null) {
                    //如果还空的话 就创建对象
                    mSingleton = new Singleton();
                }
            }
        }
        //返回该对象实例
        return mSingleton;
    }
}

4.静态内部类式

该方式保证了资源预先消耗、不必要的同步、线程的安全问题,还避免了DCL模式在某些情况下失效的问题。所以笔者建议使用该单例模式。

/**
 * Created by lijiayi on 2017/3/1.
 * 静态内部类单例
 */
public class Singleton {

    //私有化构造方法
    private Singleton() {
    }

    //获取单例对象 
    public static Singleton getInstance() {
        //返回内部类中的singleton对象 
        return SingletonHolder.singleton;
    }

    /**
     * 静态内部类
     * 第一次加载类的时候不用调用该类,创建singleton对象,
     * 只有调用getInstance()方法时才会创建该对象。
     */
    private static class SingletonHolder {
        private static final Singleton singleton = new Singleton();
    }

}

5.枚举式

枚举是线程安全的,而且任何情况下都是一个实例,他不能被序列化,也不能被反射,所以枚举单例也是一个不错的选择。



/**
 * Created by lijiayi on 2017/3/1.
 * 枚举式单例
 * 枚举单例时线程安全的,在任何情况下都是一个单例
 */
public enum SingletonEnum {
    //枚举的类型
    INSTANCE;

    // 单例中的函数
    public void todoSomethings() {
        System.out.println("do somethings");
    }
}

//枚举单例的使用
SingletonEnum.INSTANCE.todoSomethings();```
***
###6.容器实现单例
它的好处是可以统一的管理单例,安卓中getSystemService(String name)就是用这种方式实现的。
``` java 
/**
 * Created by lijiayi on 2017/3/1.
 * 容器模式单例
 * 实现了程序中单例的统一管理
 */
public class SingletonManager {
    private static Map<String, Object> singletonManagerMap = new HashMap<String, Object>();

    //私有化构造方法
    private SingletonManager() {

    }

    //注入程序中的单例
    public static void registerSingleton(String key, Object instance) {
        if (!singletonManagerMap.containsKey(key)) {
            singletonManagerMap.put(key, instance);
        }
    }

    //获取对于key值的单例对象
    public static Object getInstance(String key) {
        return singletonManagerMap.get(key);
    }
}

显示全文