以下均为一个理解,如有错误请请教,谢谢!
一个单例模式的类在任何情况下获得的该类对象都应为同一个对象,而使用new关键字必然会创建一个新的对象,因此new关键字不得在类的外部被调用,可以将构造方法设为private实现;
构造方法私有化,必须对外部提供获取对象的手段。
方式1:
public static final Singleton INSTANCE = new Sington();方式2:
private static final Singleton INSTANCE = new Singleton(); public static Singleton getInstance(){ return INSTANCE; }以上方式无法做到复杂对象的构造,可以在静态方法块中初始化对象,假设有一个config.properties的文件在资源文件夹,
public class Singleton { private static final Singleton INSTANCE = new Singleton(); private int a; private String b; static { Properties properties = new Properties(); try { properties.load(Singleton.class.getClassLoader().getResourceAsStream("config.properties")); INSTANCE.a = Integer.parseInt(properties.getProperty("a")); INSTANCE.b = properties.getProperty("b"); } catch (IOException e) { e.printStackTrace(); } } public static Singleton getInstance(){ return INSTANCE; } private Singleton(){ } public int getA() { return a; } public String getB() { return b; } public static void main(String[] args) { Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); System.out.println(s1==s2); System.out.println(s1.getA()); System.out.println(s1.getB()); } }方式3:
使用枚举类
public enum CommonError { INSTANCE(10001,"参数为空"); private CommonError(int errorCode,String errorMsg){ this.errorCode= errorCode; this.errorMsg = errorMsg; } int errorCode; String errorMsg; public int getErrorCode() { return errorCode; } public String getErrorMsg() { return errorMsg; } }以上方式均在类加载之初就实例化了单例对象,称为饿汉式,对之相对,有懒汉式的单例模式
懒汉式单例模式会在获取类对象是判断对象是否为第一次加载
public class Singleton{ private static Sington INSTANCE; private Singleton(){} public Singleton getInstance(){ if(INSTANCE==null){ INSTANCE = new Singletion(); } return INSTANCE; } }这样做明显会出现线程安全问题:在处理空值情况时,第二次获取对象请求的非空判断仍为真,导致创建另一个对象,此时两个INSTANCE会出现后创建的将新创建的INSTANCE实例覆盖,而一个对象再覆盖之前已经返回的情况,可以使用synchronized关键字同步对Singleton类的访问
public class Singleton{ private static Sington INSTANCE; private Singleton(){} public Singleton getInstance(){ syncronized(Singletion.class){ if(INSTANCE==null){ INSTANCE = new Singletion(); } return INSTANCE; } } }如果这样做,每一次访问都要对INSTANCE进行线程同步的非空判断,可以在同步操作外部再套一层非空判断,只为第一次获取单例对象的操作进行同步。
public class Singleton{ private static Sington INSTANCE; private Singleton(){} public Singleton getInstance(){ if(INSTANCE==null){ syncronized(Singletion.class){ if(INSTANCE==null){ INSTANCE = new Singletion(); } } return INSTANCE; } } }