CoreJava设计模式之单例模式

设计模式之单例模式

1.单例模式的作用:

保证整个程序在一次运行的过程中,被单例模式声明的类的对象要有且只有一个

2.实现的场景:

针对不同的应用场景,单例模式的实现要求也不同

3.单例模式的几种实现方式

(1)最最基本的单例实现:

实现步骤:

1.构造方法私有化,保证外界无法直接通过new的方式创建对象;

2.对外提供获取类的实例的静态方法,保证可以有获取的方式

3.在类的内部创建该类的对象,通过提供的公开的静态方法进行返回

public class BasicSingleTon {

    //创建唯一实例
    private static final BasicSingleTon instance = new BasicSingleTon();

    //第二部暴露静态方法返回唯一实例
    public static BasicSingleTon getInstance() {
        return instance;
    }

    //第一步构造方法私有
    private BasicSingleTon() {
    }
}

在其中将BasicSingleTon的实例化对象instance设置为私有的静态的最终的对象,其中的final只是为了保证对象在方法区中的地址无法改变,而对于对象的初始化时机没有影响。最好加上final

(2)饿汉式(静态内部类的)

//饿汉式
class A{
	private static final A instance = new A();
	public static A newInstance(){
		return instance;
	}
	private A(){}
}

缺点:初始化属性就创建对象,在未调用时一直占用堆空间内存,浪费内存

(3)懒汉式

//懒汉式
class B{
	private static B instance = null;
	public static synchronized B newInstance(){
		if(instance == null)instance = new B();
		return instance;
	}
	private B(){}
}

缺点:获取对象的静态方法是加锁的,所以并发效率低,浪费时间

(4)饿懒综合式(壮汉式)

利用静态内部类方式的单例实现:

思路:

1.返回该类的对象依赖于一个静态内部类的初始化操作;

2.在这个静态内部类初始化的时候,生成外部类的对象,然后在getInstance中返回

此处初始化的解释:

注意这里的初始化是指在JVM 类加载过程中 加载->链接(验证,准备,解析)->初始化 中的初始化。这个初始化过程将为类的静态变量赋予具体的值。

对于一个类的初始化时机有一下几种情况:

1) 使用new关键字实例化对象的时候、读取或设置一个类的静态字段(被final修饰、已在编译期把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候。

2)使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。

3)当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。

//饿懒综合式
class C{
	private static class Holder{
		static C instance = new C();
	}
	public static C newInstance(){
		return Holder.instance;
	}
	private C(){}
}

(5)双重判空式的多线程单例实现

针对于使用synchronized为get对象的静态方法加锁会影响效率的情况,只需要在多加一次判空即可优化效率

代码实现:

public class SyncSingleTon {

    private static SyncSingleTon singleTon = null;

    public static SyncSingleTon getInstance() {

        //这次判空是避免了,保证的多线程只有第一次调用getInstance 的时候才会加锁初始化
        if (singleTon == null) {
            synchronized (SyncSingleTon.class) {
                if (singleTon == null) {
                    singleTon = new SyncSingleTon();
                }
            }
        }
        return singleTon;
    }

    private SyncSingleTon() {
    }
}

(6)单例的最简单实现(enum  枚举实现) 枚举被称为单例的泛型化

枚举实现单例模式的原因是:枚举本身就是线程安全的

思路:

枚举的思想是通过共有的静态final与每个枚举常量导出实例的类,由于不能调用枚举的常量的构造方法去生成对应的对象

public enum  EnumSingleTon {
    INSTANCE
}

public class SingleTon {
    public static void main(String[] args) {
        EnumSingleTon instance = EnumSingleTon.INSTANCE;
        EnumSingleTon instance1 = EnumSingleTon.INSTANCE;

        System.out.println("instance1 == instance = " + (instance1 == instance));//输出结果为 true
    }
}

面试问题:

单例模式在面试中会常常的被遇到,因为它是考擦一个程序员的基础的扎实程度的,如果说你跟面试官说你做过项目,面试官让你写几个单例设计模式,你写不出来,你觉着面试官会相信吗?在面试时一定要认真准备每一次面试,靠忽悠即使你被录取了,你也很有可能会对这个公司不满意,好了我们言归正传,其实单例设计模式在面试中很少有人会问饿汉式写法,一般都会问单例设计模式的懒汉式的线程安全问题,所以大家一定要充分理解单例模式的线程安全的问题,就这几种模式花点时间,认真学透,面试中遇到任何关于单例模式的问题你都不会害怕是吧。

Best wish!

猜你喜欢

转载自blog.csdn.net/erpang7/article/details/82221083