设计模式之 单例模式上

什么是单例设计模式

单例设计模式(Singleton Design Pattern),就是一个类只能被实例化一次,再通俗一点就是只能被new一次。new出来这个对象,被全局共用。

单例设计模式的作用

要保证全局只有一份的时候(不管这一份是什么,重点是一份),这时就可以使用单例,比如实现一个全局唯一的资源加载类,资源加载一般只要一个地方来加载就可以了。

懒汉式单例和饿汉式单例

我们先来学习两种比较简单的单例,懒汉式单例和饿汉式单例,我们看完代码再来分析两种的区别。

懒汉式单例:

package com.itzhimei.study.design.singleton;

/**
 * www.itzhimei.com
 * 饿汉式单例
 */
public class Singleton1 {
    private static Singleton1 singleton = new Singleton1();

    private Singleton1() {

    }

    public static Singleton1 getInstance() {
        return singleton;
    }

}

懒汉式单例测试:

package com.itzhimei.study.design.singleton;

/**
 * www.itzhimei.com
 */
public class Client1 {

    public static void main(String[] args) {
        //提示错误:'Singleton1()' has private access in 'com.itzhimei.study.design.singleton.Singleton1'
        //Singleton1 s1 = new Singleton1();
        Singleton1 s1 = Singleton1.getInstance();
        Singleton1 s2 = Singleton1.getInstance();
        if(s1 == s2) {
            System.out.println("是一个对象");
        } else {
            System.out.println("不是一个对象");
        }
    }
}

输出结果:

是一个对象

你也可以多执行几次测试代码,或者将测试代码放到循环里执行一定次数,看看执行结果。

饿汉式单例:

package com.itzhimei.study.design.singleton;

/**
 * www.itzhimei.com
 * 懒汉式单例
 */
public class Singleton2 {
    private static Singleton2 singleton = null;

    private Singleton2() {

    }

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

}

懒汉式单例测试:

package com.itzhimei.study.design.singleton;

/**
 * www.itzhimei.com
 */
public class Client2 {

    public static void main(String[] args) {
        //提示错误:'Singleton2()' has private access in 'com.itzhimei.study.design.singleton.Singleton2'
        //Singleton2 s1 = new Singleton2();
        Singleton2 s1 = Singleton2.getInstance();
        Singleton2 s2 = Singleton2.getInstance();
        if(s1 == s2) {
            System.out.println("是一个对象");
        } else {
            System.out.println("不是一个对象");
        }
    }
}

输出结果:

是一个对象

懒汉式和饿汉式的区别在于,懒汉式是需要使用这个单例类时,才判断是否存在实例,不存在则创建返回实例,存在则直接返回。

这里的判断就用到了synchronized来做多线程同步,防止因为并发而造成了多个实例,就不是单例了,使用了synchronized对性能由一些影响。

而饿汉式是类的字节码被加载到JVM的时候,就会创建实例,并不需要做同步处理,缺点就是不管用不用,都直接加载到内存,有可能会造成内存浪费。

上面的的两种单例,是最简单的单例写法,也是最应该掌握的。单例还有多种写法,在实际项目和框架中,应用也非常广泛,我们下一届再来一起学习。