乐趣区

关于java:深入浅出设计模式单例模式

1. 单例模式介绍

2. 用代码演示单例模式

3. 总结

1. 单例模式介绍

定义 :所谓单例模式,就是采取肯定的办法保障在整个软件系统中, 对某个类只能存在一个实例,并且该类只提供一个获取其对象实例的办法(静态方法)。

形容
有些时候,咱们零碎只须要一个全局的对象,这样 有利于咱们协调系统的整体行为 ,节约资源。
比如说:
1)在某个服务中,须要一个对象来读取配置文件,那么有一个这样的对象来读取配置文件也就足够了。
2)比如说咱们当初要提供一个线程池,那么大部分状况下线程池这种比拟重量级的对象,几个功能模块对立有一个也就够了,因为他会有一个常驻线程数,如果线程池多了会浪费资源,所以这种对象也适宜单例的。

以上这两种状况只用了单例的对象,节约了资源,简化了治理。

2. 用代码演示单例模式

根本的实现思路
能够看出,单例模式要求 一个服务只有一个这样的对象 (永远都是雷同对象),而且 只有一个获取该实例的办法

依据这个要求,次要实现有以下两个步骤:

1)将构造方法私有化,这样其它的代码就无奈调用到该类的构造方法,就无奈应用 new 的办法来创建对象,只能通过该类提供的静态方法来失去该类的惟一实例。

2)在该类内提供一个静态方法,当咱们调用这个办法的时候,就能返回单例对象的援用。

单例模式一共有 8 种写法,
1)饿汉式(动态常量)
2)饿汉式(动态代码块)
3)懒汉式(线程不平安)
4)懒汉式(线程平安,同步写法)
5)懒汉式(线程平安,同步代码块)
6)双重查看
7)动态外部类
8)枚举

咱们来每一种写法都来介绍一遍:

1)饿汉式(动态常量 可用)

public class Singleton {private static Object target = new Object();

    private Singleton() {}

    public static Object getInstance(){return target;}

}

长处:写法比较简单,就是在类加载的时候就曾经实现了实例化。
毛病:在类装载的时候就实现初始化,没有达到 lazy Loading 的成果。如果从始至终都未用过这个实例,则可能会造成内存节约。

2)饿汉式(动态代码块 可用)

public class Singleton {private static Object target = new Object();

    private Singleton() {}

    public static Object getInstance(){return target;}
}

这种形式其实和第一种相似,优缺点也是一样的。

3)懒汉式(线程不平安 不可用)

public class Singleton3 {

    private static Object target =  null;


    private Singleton3() {}

    public static Object getInstance(){if(target==null){target = new Object();
        }
        return target;
    }

}

长处:起到了懒加载的成果,能够或多或少节约一点资源。

毛病:只能在单线程的模式下,才实用,多线程可能会创立多个单例对象,造成资源节约。(线程 A 进入了 if 判断之后,工夫片完结,另一个线程 B 也通过了这个语句,而后又调度线程 A,持续又创立了一个对象,就产生了多个实例。)

4)懒汉式(线程平安,同步写法 不举荐应用)

public class Singleton4 {

    private static Object target =  null;


    private Singleton4() {}

    public static synchronized Object getInstance(){if(target==null){target = new Object();
        }
        return target;
    }
}

长处:有懒加载的成果,又线程平安。

毛病:效率太低了,不仅仅创立的时候,每个线程想取得实例的时候,都要进行同步,其实只有在要实例的时候进行同步就行了,如果对象曾经存在的话间接返回就好了。

5)懒汉式(线程平安,同步代码块 不可用)


public class Singleton5 {

    private static Object target = null;


    private Singleton5() {}

    public static Object getInstance() {if (target == null) {synchronized (Singleton5.class) {target = new Object();
            }
        }
        return target;
    }

}

长处:优化了第四种计划,能够让获取对象的速度变快
毛病:还是会有线程平安问题,(线程 A 进入了 if 判断之后,工夫片完结,另一个线程 B 也通过了这个语句,而后又调度线程 A,持续又创立了一个对象,就产生了多个实例。)

6)双重查看 举荐应用

public class Singleton6 {

    private static Object target = null;


    private Singleton6() {}

    public static Object getInstance() {if (target == null) {synchronized (Singleton6.class) {if (target == null) {target = new Object();
                }
            }
        }
        return target;
    }

}

长处:进行了两次查看之后,就不怕多线程同时读取的状况了。

7)动态外部类 举荐应用

public class Singleton7 {


    private static class SingletonInstance {private static final Object target = new Object();
    }


    private Singleton7() {}

    public static Object getInstance() {return SingletonInstance.target;}

}

长处:类的动态属性只会在第一次加载类的时候初始化,所以在这里,JVM 帮忙咱们保障了线程的安全性,在类进行初始化时,别的线程是无奈进入的。

8)枚举 举荐应用

public enum SingletonEnum {

    INSTANCE;
    
    public void doSomething() {System.out.println("doSomething");
    }

}

长处:保障了安全性和唯一性。
毛病:所以在理论我的项目开发中,很少见人这么写过

3. 总结

单例模式应该是设计模式中最简略的一种模式了。它有以下几个因素:
1)公有的构造方法
2)指向本人实例的公有动态援用
3)以本人实例为返回值的动态的私有的办法

至于应用哪种形式获取,个别视状况而定。

退出移动版