设计模式随笔-单件模式

单件模式

单件模式是可以用来创建独一无二的,只能有一个的对象。
单件模式的类图可以说是最简单的,事实上它的类图只有一个类,但是也不要把它想的那么简单,因为它也是需要很多限制才能够安全的运行起来。

首先我们来看一个经典的单件模式的代码:

public class Singleton {
    private static Singleton singleton;

    private Singleton(){

    }

    public static Singleton getInstance(){
        if (singleton == null){
            return new Singleton();
        }
        return singleton;
    }

    //其他方法
}

构造器设置为私有的,这样只能类的内部创建对象了。外部需要得到该对象的话,就必须调用getInstance方法来获取,而getInstance里面判断了如果singleton对象为空则创建这个对象,否则返回该对象,这样就创造了单件的对象了。

单件模式与之间命名一个静态对象相比有一个优点,就是能够延迟实例化。不会在项目加载的时候就实例化了对象。

单件模式:确保一个类只有一个实例,并提供一个全局访问点。

简单单件模式的缺点

但是对于简单的单件模式,在多线程的情况下,并不适用的。如下图是两个线程同时请求单件对象:
多线程单件模式
这样就有两个单件对象了。这可能会让系统存在无法发现的问题,怎么查也查不到。
解决方法,使用同步代码块:

public class Singleton {
    private static Singleton singleton;

    private Singleton(){}

    public static synchronized Singleton getInstance(){
        if (singleton == null){
            return new Singleton();
        }
        return singleton;
    }

    //其他方法
}

但是使用同步代码块的话,就会造成性能上的问题,这就引申出了另外一个问题了。而且单件模式的这个代码块,只是在创建对象的时候有用,之后每次调用都成为了累赘了。

能够改善多线程吗?
1.如果getInstance的性能对程序不是关键的,那么就什么都不用管。
对于不是程序的关键,使用同步代码块,既简单又有效。但是可能会造成效率下降100倍。

2.急切的初始化对象,而不用懒加载的方法。
如果程序总是使用单件,并且程序在启动时负担不重,可以考虑使用立即初始化单件对象。

public class Singleton {
    private static Singleton singleton = new Singleton();

    private Singleton(){}

    public static synchronized Singleton getInstance(){
        return singleton;
    }
    //其他方法
}

这个方法依赖了JVM加载这个类时就创建了一个单件对象。JVM保证在任何线程访问之前就创建好了对象。

3.用“双重检查加锁”在getInstance()中减少同步的使用。

public class Singleton {
    //volatile 只适用于java5以上的版本哦,volatile能保证对象被初始化完成之后能够正确处理多线程
    private volatile static Singleton singleton;

    private Singleton(){}

    public static Singleton getInstance(){
        if (singleton == null){
            synchronized (Singleton.class) {
                if (singleton == null) {
                    return new Singleton();
                }
            }
        }
        return singleton;
    }

    //其他方法
}

如果性能是你关注的,那么使用这种方法会大大减少getInstance的时间消耗。

总结

有些对象我们只需要一个,比方说:线程池、缓存、对话框、注册表等等。这时候不妨使用单件模式来实现。

单件模式:确保一个类只有一个实例,并提供一个全局访问点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值