小伙的java之旅——GOF23-单例模式

来源:互联网 发布:淘宝食品许可证 编辑:程序博客网 时间:2024/04/28 20:46

单例模式:

核心作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。

饿汉式:

/**     * 单利模式:饿汉式加载     *      饿汉单例模式代码中,static变量会在类装载时初始化,此时也不会涉及多个线程对象访问对象的问题。虚拟机保证只会装载一次该类,肯定不会发生并发访问的问题。     * 因此,可以省略synchronized关键字     *      问题:如果只是加载本类,而不是要调用getInstance(),甚至永远没有调用,则会造成资源浪费。     * @author zw     *     */public class HungryLoad {//类初始化时,立即加载这个对象(没有延时加载的优势)。加载类时,天然是线程安全的。private static HungryLoad instance = new HungryLoad();//私有化构造器。private HungryLoad() {}//方法没有同步,调用效率高。public static HungryLoad getInstance(){    return instance;    }}

懒汉式

/** * 单例模式:懒汉式加载 *      延迟加载,懒加载!真正用的时候才加载。 *      问题:资源利用率高了。但是每次调用getInstance()方法都要同步,并发效率较低。 * @author zw * */public class LazyLoad {//类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)private static LazyLoad instance;//私有化构造器private LazyLoad() {    //防止通过反射创建多个对象    if (instance != null) {        throw new RuntimeException();    }}//方法同步,调用效率低。public static synchronized LazyLoad getInstance(){    if (instance == null) {        instance = new LazyLoad();    }    return instance;    }}

静态内部类

/** * 单例模式:静态内部类(也是一种懒加载) *      外部类没有static属性,则不会像饿汉式那样立即加载对象。 *      只有真正调用getInstance(),才会加载静态内部类,加载类时是线程安全的。instance是static final 类型,保证了内存中只有这样一个实例存在, * 而且只能被赋值一次,从而保证了线程安全性。 *      兼备了并发高效调用和延迟加载的优势! * @author zw * */public class StaticInnerclassLoad {private static class InnerClass{    private static final StaticInnerclassLoad instance = new StaticInnerclassLoad();}private StaticInnerclassLoad() {}public static StaticInnerclassLoad getInstance() {    return InnerClass.instance;    }}

枚举

/** * 单例模式:枚举加载 *      实现简单 *      枚举本身就是单例模式,由JVM从根本上提供保障!避免通过反射和反序列化的漏洞! *      问题:无延迟加载。 * @author zw * */public enum EnumLoad {/** * 定义一个枚举元素,它就代表了Singleton的一个实例 */INSTANCE;/** * 单例可以有自己的操作 * @return  */public void singletonOperation(){    //功能处理    System.out.println("枚举加载的功能");    }}

开发时,如果类创建对象的代价很高,就用延时加载(懒汉式);类调用效率非常频繁,用饿汉式

单例对象:占用 资源少;不需要延时加载。        枚举式     好于      饿汉式单例对象:占用 资源大;需要延时加载。        静态内部类式      好于      懒汉式

防止通过反射创建多个对象,在构造方法中加
if (instance != null) {
throw new RuntimeException();
}

单例模式应用的场景一般发现在以下条件下:

  (1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。

  (2)控制资源的情况下,方便资源之间的互相通信。如线程池等。

0 0