单例模式

单例模式

单例模式跟静态的区别

观点一:(单例 )

单例模式比静态方法有很多优势:

  • 单例可以继承类,实现接口,而静态类不能(可以集成类,但不能集成实例成员);
  • 单例可以被延迟初始化,静态类一般在第一次加载是初始化;
  • 单例类可以被集成,他的方法可以被覆写;
  • 单例类可以被用于多态而无需强迫用户只假定唯一的实例。举个例子,你可能在开始时只写一个配置,但是以后你可能需要支持超过一个配 置集,或者可能需要允许用户从外部从外部文件中加载一个配置对象,或者编写自己的。你的代码不需要关注全局的状态,因此你的代码会更加灵活。

观点二:(静态方法 )

静态方法中产生的对象,会随着静态方法执行完毕而释放掉,而且执行类中的静态方法时,不会实例化静态方法所在的类。如果是用singleton, 产生的那一个唯一的实例,会一直在内存中,不会被GC清除的(原因是静态的属性变量不会被GC清除),除非整个JVM退出了。这个问题我之前也想几天,并 且自己写代码来做了个实验。

观点三:(Good! )

由于DAO的初始化,会比较占系统资源的,如果用静态方法来取,会不断地初始化和释放,所以我个人认为如果不存在比较复杂的事务管理,用 singleton会比较好。

单例的七种写法

懒汉式(线程不安全)

public class Singleton {
  private static Singleton singleton;
 
  private Singleton() {
  }
 
  public static Singleton getInstance() {
    if (singleton == null) {
      singleton = new Singleton();
    }
 
    return singleton;
  }
}

懒汉(线程安全 )

public class Singleton {
    private static Singleton singleton;

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

饿汉

public class Singleton {
    private static Singleton singleton = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return singleton;
    }
}

饿汉变种

public class Singleton {
  private static Singleton instance = null;
 
  static {
    instance = new Singleton();
  }
 
  private Singleton() {
  }
 
  public static Singleton getInstance() {
    return this.instance;
  }
}

静态内部类

public class Singleton {

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    private Singleton() {}

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程

它跟第三种和第四种方式不同的是(很细微的差别):第三种和第四种方式是只要Singleton类被装载了,那么instance就会被实例化(没有达到lazy loading效果),而这种方式是Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。

想象一下,如果实例化instance很消耗资源,我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。这个时候,这种方式相比第三和第四种方式就显得很合理

枚举

public enum Singleton {

    INSTANCE;

    public void whatEverMehthod() {}
}

双重校验锁

public class Singleton {
    private volatile static Singleton singleton;

    private Singleton() {}

    public static Singleton getSingleton() {
        if (singleton == null) {
            synchronized(Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }

        return singleton;
    }
}
posted @ 2023-07-11 00:40  一只盐桔鸡  阅读(36)  评论(0编辑  收藏  举报