校招准备系列:每天一道算法题(9)-单例

校招准备系列:每天一道算法题(9)-单例

单例 是最为最常见的设计模式之一。对于任何时刻,如果某个类只存在且最多存在一个具体的实例,那么我们称这种设计模式为单例。例如,对于 class Mouse (不是动物的mouse哦),我们应将其设计为 singleton 模式。

你的任务是设计一个 getInstance 方法,对于给定的类,每次调用 getInstance 时,都可得到同一个实例。

思考:首先,我们来了解一下单例模式,单例模式是一种对象创建模式,用于产生一个对象的具体实例,他可以确保系统中一个类只产生一个实例,其好处在于:1)对于频繁使用 对象,可以省略创建对象所花费的时间,尤其对于一些重量级对象;2)由于new操作次数减少,因而对系统内存的使用频率也会降低,能减轻GC压力,缩短GC停顿时间!So,对于系统的关键组件和被频繁使用的对象使用单例模式可以有效的改善系统的性能。。。

单例模式的核心在于通过一个接口返回唯一的对象实例!
代码:

/**
 * 单例模式:饿汉式
 */
public class SingletonDemo1 {
    private SingletonDemo1(){       
    }
    private static SingletonDemo1 instance = new SingletonDemo1();//static实例变量在类加载到内存时就会初始化 线程安全
    public static SingletonDemo1 getInstance(){
        return instance;
    }
}

从饿汉式代码我们可以看出,1)单例类必须有一个private的构造函数,只有这样才能确保单例不会在系统中的其他代码内被实例化;2)instance成员变量和getInstance()方法必须是static的。

阅读饿汉式单例类的代码,我们知道,其不足在于无法对instance实例做延迟加载,static实例变量在类加载到内存时就会初始化,单例对象就会被创建,其创建的对象是线程安全的!

改进代码:

/**
 * 单例模式:饱汉式
 */
public class SingletonDemo2 {
    private SingletonDemo2(){

    }
    private static SingletonDemo2 instance = null;
    public static synchronized SingletonDemo2 getInstance(){
        if (instance == null) {
            instance = new SingletonDemo2();
        }
        return instance;
    }
}

在这里的处理中,我们首先对静态成员变量instance初始值赋值null,确保系统启动时没有额外的负载;其次在getInstance()工厂方法中,判断当前单例是否已经创建,若存在则返回,否则就再简历单例!
PS:方法中使用了Synchronized关键字,避免多线程环境下,导致多个单例创建!

饱汉式单例模式虽然解决了延迟加载的问题,但加入Synchronized关键字却增加了系统的开销,所以还需要进一步改进,想到的方法是使用内部类,这种方式使用内部类维护单例的实例,当SingletonDemo3 被加载的时候其内部类并不会被初始化,故可确保SingletonDemo3 类被加载到jvm时,不会初始化单例类,而当调用getInstance方法时,才会加载SingletonHolder,从而初始化instance,同时,由于其实例的建立是在类加载时完成,故天生对多线程友好,不需使用同步关键字,实现代码如下:

/**
 * 单例模式:内部类
 */
public class SingletonDemo3 {
    private SingletonDemo3(){

    }
    private static class SingletonHolder{
        private static SingletonDemo3 instance = new SingletonDemo3();
}
    public static SingletonDemo3 getInstance(){
        return SingletonHolder.instance;
    }
}

当然除了上面三种方式实现单例模式,我们还有常用的一种最简单的方法,那就是枚举!!

/**
 * 枚举类方式 最佳实践 推荐
 */
public enum SingletonDemo3 {
    INSTANCE;
    public static void say(String str){
        System.out.println("hello"+str);
    }
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值