java设计模式(三)---单例模式

一、单例模式的基本定义

​ 一个类有且仅有一个实例,并且提供了一个全局的访问点

二、单例模式适用场景:

1.面试被问到的几率较高
2.需要频繁的实例化然后销毁对象
3.创建对象时耗时或者消耗资源过多,但又经常用到的对象
4.有状态的工具对象
5.频繁访问数据库或者文件的对象
6.资源共享情况下,避免资源操作时导致性能损耗
7.控制资源的情况下,方便资源之间的互相通信,如线程池

三、单例模式的特点:

1.只能有一个实例
2.单例必须是自己来创建自己的唯一实例
3.单例必须给其他使用者提供接口

四、实现单例模式:

​ 根据单例模式的特点,创建一个单例模式的实例。

public class SingletonDemo {
    /**
     * 因为只能有一个实例,所以不能允许随便new
     */
    private SingletonDemo() {
    }

    /**
     * 因为构造方法是私有的,所以需要定义静态变量,防止可以直接被其他类调用,定义为私有的
     */
    private static SingletonDemo singletonInstance = null;

    /**
     * 其他类使用实例时只能通过静态方法获取
     *
     * @return
     */
    public static SingletonDemo getSingletonInstance() {
        if(singletonInstance==null){
            singletonInstance = new SingletonDemo();
        }
        return singletonInstance;
    }
}

以上的单例模式是根据单例模式特点最容易想到的一种实现方式,如果此单例一直没有被用到,则一直不会初始化,对资源浪费较少,但是缺点是非线程安全的。面试的时候一般不推荐写这种。

线程安全可以定义singletonInstance熟悉时直接new一个对象,这样就是线程安全的。静态变量是在加载类的时候初始化的,所以获取单例实例的时候就可以直接获取。但是缺点是每次加载类的时候都会初始化,如果用不到单例实例,就会对资源造成一定的浪费。但是这种实现方式容易记录,可以面试的时候捎带上这种实现方式。

public class SingletonDemo {
    /**
     * 因为只能有一个实例,所以不能允许随便new
     */
    private SingletonDemo() {
    }

    /**
     * 因为构造方法是私有的,所以需要定义静态变量,防止可以直接被其他类调用,定义为私有的
     */
    private static SingletonDemo singletonInstance = new SingletonDemo();

    /**
     * 其他类使用实例时只能通过静态方法获取
     *
     * @return
     */
    public static SingletonDemo getSingletonInstance() {
        return singletonInstance;
    }
}

如果比较在意资源的优化(不使用不初始化),同样线程安全除了加载时初始化也可以使用 synchronized关键字来保证线程安全 ,这样可以保证不使用不出初始化,但是缺点是效率较低,大多数情况下是不需要同步的,但是加了synchronized每次调用都会加锁。

public class SingletonDemo {
    /**
     * 因为只能有一个实例,所以不能允许随便new
     */
    private SingletonDemo() {
    }

    /**
     * 因为构造方法是私有的,所以需要定义静态变量,防止可以直接被其他类调用,定义为私有的
     */
    private static SingletonDemo singletonInstance = null;

    /**
     * 其他类使用实例时只能通过静态方法获取
     *
     * @return
     */
    public static synchronized SingletonDemo getSingletonInstance() {
        if(singletonInstance==null){
            singletonInstance = new SingletonDemo();
        }
        return singletonInstance;
    }
}

针对以上实现方式,可以继续优化使用效率。synchronized除了可以修饰方法以外还可以修饰代码块,因为同步使用的时候只是在初始化的时候需要同步,可以双重校验的方式对以上实现方式加强。

public class SingletonDemo {
    /**
     * 因为只能有一个实例,所以不能允许随便new
     */
    private SingletonDemo() {
    }

    /**
     * 因为构造方法是私有的,所以需要定义静态变量,防止可以直接被其他类调用,定义为私有的
     */
    private static SingletonDemo singletonInstance = null;

    /**
     * 其他类使用实例时只能通过静态方法获取
     *
     * @return
     */
    public static SingletonDemo getSingletonInstance() {
        //只有singletonInstance为空的时候使用synchronized
        if(singletonInstance==null){
            synchronized (SingletonDemo.class){
                //再次校验singletonInstance是否为空
                if(singletonInstance==null){
                    singletonInstance = new SingletonDemo();
                }
            }
        }
        return singletonInstance;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值