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)以本人实例为返回值的动态的私有的办法

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