前几天在上Java基础课的时候,讲到private关键字的作用,就是所有被private修饰的成员变量和常量都只能在本类中使用。也就说构造方法一旦被private修饰就只能在本类中使用。不能再外部创建本类的实例。一般的应用场景有两个,一个是工具类,我们就是不希望别人创建对象,所以把构造方法私有化。另一个就是单例设计模式中,我们也不希望别人随意创建实例,要想得到本类的实例,必须调用给提供的static的获取实例的方法才可以。今天咱们就来总结一下,单例设计模式的几种常见的写法有什么优缺点。
第一种,懒汉式,线程不安全
[AppleScript] 纯文本查看 复制代码 public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
第二种,懒汉式,线程安全
[AppleScript] 纯文本查看 复制代码 public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这种写法,虽然多线程的时候不会出问题,但是效率太低。
第三种,饿汉式
[AppleScript] 纯文本查看 复制代码 public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
在类加载时创建,避免多线程的问题。
第四种,静态内部类
[AppleScript] 纯文本查看 复制代码 public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
也是用类加载机制来保证初始化时只用一个线程,但是好处是SingleTon被加载了,实例不一定被穿件,只用调用getInstance()方法时,才会显示的加载SingletonHolder,从而实例化Singleton.
第五种方式,枚举
[AppleScript] 纯文本查看 复制代码 public enum Singleton {
INSTANCE;
public void method() {
}
}
第六种,双重检校
[AppleScript] 纯文本查看 复制代码 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;
}
}
|