单例模式详解

    科技2022-07-10  102

    单例模式

    以下均为一个理解,如有错误请请教,谢谢!

    单例模式的设计要求:

    一个单例模式的类在任何情况下获得的该类对象都应为同一个对象,而使用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; } } }
    Processed: 0.015, SQL: 8