设计模式之创建型模式:单例模式

单例模式,顾名思义就是只存在一个类的实例,避免多实例造成的内存浪费。

1.饿汉模式

public class SingletonPattern {

    //第一种,饿汉模式
    private SingletonPattern() {
    }

    private static SingletonPattern singleton = new SingletonPattern();

    public static SingletonPattern getInstance() {
        return singleton;
    }
}

这种方式在类加载时就完成了初始化,基于类加载的模式,避免了线程同步的问题,但是没有很好的控制加载的时机,可能会造成内存的浪费。

2.懒汉模式

public class SingletonPattern {

    //第二种 懒汉式
    private SingletonPattern() {
    }

    private static SingletonPattern singleton2 = null;

    public static SingletonPattern getInstance2() {
        if (singleton2 == null) {
            singleton2 = new SingletonPattern();
        }
        return singleton2;
    }
}

这种模式弥补了饿汉式的加载时机的把握,在第一次调用的时候去初始化,但是线程是不安全的的,为了解决线程多安全的问题,我们有了下面这中写法。

3.懒汉模式,线程安全

public class SingletonPattern {

    //第三种 懒汉模式,线程安全
    private SingletonPattern() {
    }

    private static SingletonPattern singleton3 = null;

    private static synchronized SingletonPattern getInstance() {
        if (singleton3 == null) {
            singleton3 = new SingletonPattern();
        }
        return singleton3;
    }
}

这种写法处理了线程的安全问题,但是每次都会进行同步,降低了代码的效率,造成不必要的开销,所以是不建议使用的,用锁的形式来保证线程安全是没错的,只是要考虑锁的位置。

4.双重检查模式

public class SingletonPattern {


    //第四种 懒汉模式双重锁

    private SingletonPattern() {
    }

    private static volatile SingletonPattern singleton4 = null;

    public static SingletonPattern getInstance() {

        if (singleton4 == null) {
            synchronized (SingletonPattern.class) {
                if (singleton4 == null) {
                    singleton4 = new SingletonPattern();
                }
            }

        }
        return singleton4;
    }
}

首先是进行了两次if判断,第一次是为了不必要的同步操作,第二次是在对象为null的情况下,才初始化的。这里用到的volatile关键字,会屏蔽JVM的一些优化操作,对性能会有一些降低,所以我们推荐下面这种写法。

5.静态内部类单例模式

public class SingletonPattern {

    //第五种 静态内部类
    private SingletonPattern() {
    }

    private static class Singleton {
        private static final SingletonPattern SINGLE = new SingletonPattern();
    }

    public static SingletonPattern getInstance() {
        return Singleton.SINGLE;

    }
}

第一次加载SingletonPattern类的时候,不会去初始化内部类,只有在调用getInstance()方法之后,才会加载内部类并且初始化静态变量,并且也保证了线程的安全性。

单例的优点

单例模式只产生一个实例,减少了内存的损耗,减少了性能的开销,避免了对资源的多重占用,可以在全局范围上进行管理。

单例的缺点

单例模式是不易扩展的,单例的方法不能生成子类的对象,必须要重写单例类才可以;如果单例方法需要传递Context的话,要小心内存泄漏的风险。

猜你喜欢

转载自blog.csdn.net/xiang_min/article/details/81046413