设计模式--单例模式

如果文章哪里写错了,希望各位大哥大姐好心指出,十分感激

正文

什么是单例模式?

  单例模式就是指我只会生成一个实例对象,你在使用过程中,虽然获取了多次,但你每次获取到的都是同一个对象。

为什么要使用单例模式?

  单例的出现主要能解决两个问题:
    1:提供一个全部唯一访问点,例如有一些全局变量,这些变量不会经常变化。
    2:控制一些创建过程复杂的共享资源对象创建,例如数据库连接,或者日志文件的写入。创建过程比较耗时复杂,又不宜创建过多对象。
  对于这两种情况,我们就可以使用单例,去控制对象的无意义创建,减少内存消耗。

怎样使用单例模式?
  1:构造方法全部私有化。
  2:提供一个唯一的静态方法去获取唯一实例对象。

单例有4种(网上有很多说5种7种,其实最重要的也就这4种):
  1:饿汉模式单例(由classLoader控制,加载类时就创建了实例对象)
  2;双重判断的懒汉单例(获取实例对象时才创建,用了synchronized关键字控制多线程并发)
  3:静态内部类的懒汉单例(由classLoader控制,在获取实例对象时才会加载内部类,从而实现了懒加载)
  4:枚举模式的单例(将枚举当成普通类来使用,既可以防止多线程并发,也可以防止反序列化创建对象)

饿汉模式单例和静态内部类的懒汉单例由classLoader来控制单例,这可能会产生两个或多个实例,原因:

  如果当前的类的类加载器是自定义类加载器classLoader1,第一次加载单例类的时,根据双亲委派机制,他会委托“父亲”classLoader来进行加载,如果都没有能加载的,那就classLoader1来加载。

  但如果好死不死,另外一个地方在获取这个单例类的时候,他用的是自定义类加载器classLoader2,根据双亲委派机制让他父亲来加载,又刚好碰巧还是没能加载上,那就是classLoader2来加载。

  这样子这个单例就有了两个实例。

 

我个人更喜欢用枚举模式的单例,代码少了,还不用管多线程并发,头发瞬间多了

 

饿汉模式单例

/**
 *     简单饿汉单例
 * */
class Single1 {
    private static Single1 instance = new Single1();
    /**
     *     如果初始化单例很复杂,可以在静态代码块中进行初始化工作
     * */
    static {
        instance = new Single1();
        /** 复杂的初始化工作 */
    }
    private Single1() {}
    
    public static Single1 getInstance() {
        return instance;
    }

}

 

双重判断的懒汉单例

/**
 *     双重判断的懒汉单例
 * */
class Single2 {
    private static Single2 instance;
    
    private Single2() {}
    /**
     *     因为进行了两次if(instance == null)判断,所以就叫双重判断,可以防止多线程冲突
     * */
    public static Single2 getInstance() {
        if(instance == null) {
            synchronized(Single2.class){
                if(instance == null) {
                    instance = new Single2();
                }
            }
        }
        return instance;
    }
}

 

静态内部类的懒汉单例

/**
 *     静态内部类的懒汉单例
 * */
class Single3 {
    private static class InnerClass{
        private static Single3 instance = new Single3();
    }
    
    private Single3() {}
    
    public static Single3 getInstance() {
        return InnerClass.instance;
    }
}

 

枚举模式的单例

/**
 *     枚举的单例
 * */
enum Single4{
    instance;
    /** 一般业务方法 */
    public void operation() {
        
    }
}

 

posted @ 2020-05-05 00:57  _ME  阅读(126)  评论(0)    收藏  举报