java设计模式:单例模式

163 阅读3分钟

设计模式GOF23

分类

(1)创建型模型

应用:对象的创建
  • 单例模式,工厂模式,抽象工厂模式,建造者模式,原型模式

(2)结构型模式

  • 适配器模式,桥接模式,装饰模式,组合模式,外观模式,享元模式,代理模式

(3)行为型模型

  • 模板方法模式,命令模式,迭代器按模式,观察者模式,中介者模式,备忘录模式,解释器模式,状态模式,策略模式,职责链模式,访问者模式

1.单例模式

作用

  • 保证一个类只有一个对象,并且提供一个可以访问该实例的全局入口

优点

  • 减少系统性能开销,当一个对象的创建需要占用很多资源时,如读取配置,产生其他依赖对象时,则可以在应用启动时创建一个单例对象

实现方式

  • 饿汉式(线程安全,不能延时加载)

/**
 * 饿汉式-单例模式:
 */
public class SingletonMode {

    /**
     * (1)私有化构造器
     */
    private SingletonMode(){

    }

    /**
     * (2)私有静态变量创建唯一实例(类初始化时,立即创建实例,由于类的初始化本身是线程安全的,所以不需要再添加锁控制.所以效率也高)
     */
    private static SingletonMode instance = new SingletonMode();

    /**
     * (3)对外暴露一个全局访问接口
     */
    public static SingletonMode getInstance(){
        return instance;
    }

}
  • 懒汉式(线程安全,可以延时加载)
/**
 * 恶汉式-单例模式:
 */
public class SingletonMode2 {

    /**
     * (1)私有化构造器
     */
    private SingletonMode2(){

    }

    /**
     * (2)申明私有化唯一实例
     */
    private static SingletonMode2 instance;

    /**
     * (3)对外暴露一个全局访问接口,在第一次调用getInstance方法时,才创建实例,实现了延迟加载;
     * 这里的对象创建需要加锁synchronized,所以调用效率低
     */
    public synchronized static SingletonMode2 getInstance(){
        if(instance == null){
            return new SingletonMode2();
        }
        return instance;
    }

}
  • 静态内部类(比较推荐)(上面两种写法因为JVM本身的原因,可能会偶发出现问题,静态内部类和枚举的写法是比较推荐的
/**
 * 静态内部类-单例模式
 * 推荐使用。既可以实现懒加载,又可以保证线程安全
 */
public class SingletonMode3 {

    /**
     * (2)定义静态内部类,内部类成员变量为唯一实例
     *
     */
    private static  class Mode3{
        //类静态变量的加载是线程安全
        private static final SingletonMode3 instance = new SingletonMode3();
    }

    /**
     * (3)对外提供访问入口
     * 因为静态内部类不会随着外部类的加载而加载,而是用到了它的时候才会被加载,所以这里实现了懒加载
     * @return
     */
    public static  SingletonMode3 getInstance(){
        return Mode3.instance;
    }

    /**
     * (1)私有化构造器
     */
    private SingletonMode3(){

    }
}
  • 枚举实现单例(这种写法是最好的,唯一的缺点就是不能懒加载)
/**
 * 使用枚举-单例模式
 * 这种是最好的
 * */
public enum SingletonMode4 {
    /**
     * (1)获取唯一实例,一步到位
     * INSTANCE 本身就是 SingletonMode4类的一个实例,会在类加载的时候创建。本身就是线程安全而且唯一,只是没有懒加载.而且枚举的构造方法本身就只能是私有的。
     * */
    INSTANCE;

    /**
     *
     *  doSomeThing可以写一些业务代码
     */
    private void doSomeThing(){

    }

    /***
     * 用法 eg:  SingletonMode4.INSTANCE.doSomeThing();
     *
     */
}