设计模式

<二>单例模式

2019-08-25  本文已影响0人  将代码写成诗

定义:

Ensure a class has only one instance,and provide a global point of access to it.(确保某一个类只有一个实例,而且自行实例化并向整个系统提供整个单例)

单例模式的通用类图如下


editByWpp.png
单例模式的2种常见表现形式
/**
 * @author wpp25
 * @date 2019/8/25 9:44
 * 描述:饿汉式单例
 */
public class HungerSingleton 
    private HungerSingleton(){}
    private static final HungerSingleton hungerSingleton= new HungerSingleton();
    public static HungerSingleton newInstance(){
        return hungerSingleton;
    
}
/**
 * @author wpp25
 * @date 2019/8/25 9:43
 * 描述: 懒汉式单例
 */
public class LazySingleton {
    private LazySingleton(){}

    private static LazySingleton lazySingleton = null;

    public static LazySingleton newInstance(){
        if (lazySingleton == null) {
            lazySingleton = new LazySingleton();
        }

        return lazySingleton;
    }
}

单例模式的优缺点

优点

缺点

单例模式的注意事项

首先,在高并发的情况下,请注意单例模式的线程同步情况;比如懒汉式单例的获取方式中在并发量比较大的时候就有可能会出现问题?如一个线程A执行到lazySingleton = new LazySingleton();但是还没有获取到对象(对象的获取是需要时间的),第二个线程B也在执行,执行到if (lazySingleton == null) 时,判断为真,这样内存中就会有两个对象了。
解决线程不安全的方法有很多,可以在newInstance方法前加synchronized关键字,也可以在newInstance方法内增加synchronized 同步代码块的形式实现,但都不是最优秀的单例模式(建议读者使用饿汉式)
其次,需要考虑对象的复制情况。在java中,对象默认是不可以被复制的,若实现了Cloneable接口,并实现了clone方法,则可以直接通过复制方式创建一个新对象,对象的复制时不需要调用类的构造器的,因此即使构造被私有化,对象仍然可以被复制,解决该方法最好的方法就是不去实现Cloneable接口

最佳实践

如在Spring中,每个Bean默认就是单例的,这样做的优点是Spring容器可以管理这些Bean的生命周期,决定什么时候创建出来,什么时候销毁,以及销毁时做怎样的处理等,如果采用非单例模式(Prototype类型),则Bean的初始化后的管理交由J2EE容器,Spring容器不会再跟踪管理Bean的生命周期。
使用单例模式需要注意的一点的就是JVM的垃圾回收机制,如果我们的一个单例对象在内存中长久不实用,jvm就会认为该对象是一个垃圾,在cpu资源空闲的情况下就会将该对象清理掉,下次调用时就需要重新产生一个对象。如果我们在应用中使用单例类作为有状态值(如计数器)的管理,则会出现恢复原状的情况,应用就会出现问题。如果确实需要单例模式来记录有状态的值,哟两种方法可以解决

上一篇 下一篇

猜你喜欢

热点阅读