设计模式学习——单例模式

有次面试的时候直接被虐了,其中一个问题是要我说单例模式的实现方式。当时直接答了懒汉和饿汉模式,然后又被问有没有其他方式,效率会更高些的,简直一脸的懵逼,回去后查了下,确实还有别的。

什么是单例?----单例就是确保一个类只有一个实例,而且自行实例化,并向系统提供这个实例。单个例还可以扩展,就是多例模式。

有些经验的,根据定义也知道怎么实现,就是构造方法私有化,不让外界实例化(当然反射技术来实现暂不考虑),然后自己实例化一个并提供一个静态的方法将它抛出,这就引出了我们都知道的两种模式:1.懒汉模式      2.饿汉模式

懒汉模式:既然是懒汉,那就说明这家伙比较懒,你问他要他才给你做,不要他就在那里闲着。怎么实现呢?

 

public class Single { private static Single mSingle = null; private Single(){ } public static Single getInstance(){ if (mSingle == null) { return new Single(); }else { return mSingle; } }}

 

这就是一个简单的单例,但是这样并不安全,尤其是线程多的时候,可能会产生多个实例。然后改进下:

 

public class Single { 

private static Single mSingle = null;

 private Single(){ } 

public synchronized static Single getInstance(){ 

if (mSingle == null) { 

return new Single(); 

}else { 

return mSingle; 

}

}

 
给获取实例的方法加锁,这样可以保证线程的安全。但是这样效率比较低,可以使用双重校验锁,改进如下
 
public class Single {
    private static  Single mSingle = null;
    private Single(){ }
    public static Single getInstance(){
        if (mSingle == null) {
            synchronized (Single.class){
                if (mSingle == null){
                    mSingle = new Single();
                }
            }
        }
        return mSingle;
    }
}
 
改进后就不会每次获取实例都去检查锁了,只有第一次才会。
饿汉模式:饿汉嘛,自己就迫不及待的把实例做出来了,饿汉模式本身是线程安全的。但它不是懒加载的,实例一开始就被实例化了。
public class Single {
    private static  final Single mSingle = new Single();
    private Single(){ }
    public synchronized static Single getInstance(){
        return mSingle;
    }
}
静态内部类模式:属于懒加载,饿汉的升级public class Single {
    private static class SingleBuild {
        private static final Single INSTANCE = new Single();
    }

    private Single() {}

    private static final Single getInstance() {
        return SingleBuild.INSTANCE;
    }
}
个人比较喜欢懒汉中的双重检查锁的写法,通俗而且线程安全,并且效率也高。那次面试估计面试官要的答案就是双重检查锁的方法。当然也可以独立说成一种写法,另外还有查到使用枚举来实现单例,太不常用,就不写了。
多例模式(单例的变种)
//这里采用饿汉的模式
public class Single {
    private static int MAX_NUMBER = 3;
    private static ArrayList<Single> list = new ArrayList<Single>();
    static {
        for (int a = 0;a<MAX_NUMBER;a++){
            list.add(new Single());
        }
    }
    private Single(){}
    public static Single getInstance(){
        Random random = new Random();
        //从实例中随机获取一个random.nextInt(3)会返回0,1,2
        return list.get(random.nextInt(MAX_NUMBER));
    }
}


如果需要使用到多例,那想必逻辑也会稍微复杂,这里的代码只是一个简单的实现,可以根据实际来编写逻辑。
 



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值