单例模式详解

单例模式

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

单例模式的设计要求:

一个单例模式的类在任何情况下获得的该类对象都应为同一个对象,而使用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;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值