Java设计模式学习之单例模式

何为单例

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象

单例的用途

保证一个类仅有一个实例,并提供一个访问它的全局访问点,主要解决一个全局的类频繁创建和销毁

单例实现方式

饿汉式

饿汉式即不管是否使用都会在初始化的时候创建该类的实例

  1. 饿汉式单例基础写法
public class HungrySingleton {

    /**
     * 不加final容易被误操作覆盖
     */
    private static final HungrySingleton instance = new HungrySingleton();

    private HungrySingleton() {
    }

    public static HungrySingleton getInstance() {
        return instance;
    }
}

2.静态代码块实现单例

public class HungryStaticSingleton {

    private static  final HungryStaticSingleton instance;


    private HungryStaticSingleton(){}
    static {
        instance = new HungryStaticSingleton();
    }

    public static  HungryStaticSingleton getInstance(){
        return instance;
    }
}

以上两种写法,在本质上并无区别,只是静态代码块实现显得比较优雅而已

懒汉式

懒汉式单例即只在对象需要的时候被创建,避免单例对象不被使用时浪费资源

  1. 懒汉式单例基础写法
public class LazySingleton {
    private static   LazySingleton instance;
    private LazySingleton(){}
    /**
     * 懒汉式  线程不安全,不可用
     */
    public  static  LazySingleton getInstance(){
//        第一访问时做判断,第二次以后直接返回
        if (instance ==null){
            instance = new LazySingleton();
        }
        return instance;
    }

    /**
     * 同步方法,线程安全,效率低,不推荐
     */
    public static synchronized LazySingleton synInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }


    /**
     * 线程不安全,会产生多个实例,不可用
     */
    public static LazySingleton lockSingleton() {
        if (instance == null) {
            synchronized (LazySingleton.class) {
                instance = new LazySingleton();
            }
        }
        return instance;
    }

}

2.懒汉式双重校验锁写法

public class LazyDoubleCheckSingleton {


    private static volatile LazyDoubleCheckSingleton lazySingleton;

    private LazyDoubleCheckSingleton() {
    }

    /**
     * 双重锁校验
     * 缺点:性能
     */
    public static LazyDoubleCheckSingleton lock2Singleton() {
//        第一次进入做判断
        if (lazySingleton == null) {
//          synchronized 方法锁
            synchronized (LazyDoubleCheckSingleton.class) {
                if (lazySingleton == null) {
                    lazySingleton = new LazyDoubleCheckSingleton();
//                   不加volatile 指令重排序问题
//                   1. Memory = allocate() 分配对象的内存空间
//                    2.ctorInstance() 初始化对象
//                    3.instance = memory 设置instance指向刚分配的内存
//                    JVM和CPU优化,发生指令重排
                }
            }
        }
        return lazySingleton;
    }
}

3.静态内部类实现单例模式

public class LazyInnerClassSingleton {

    private LazyInnerClassSingleton(){}
    private static  class LazyHolder{
        public static  final LazyInnerClassSingleton SINGLETON = new LazyInnerClassSingleton();
    }

    /**
     * 静态内部类,线程安全,主动调用时才实例化,延迟加载效率高,推荐使用
     */
    public static final LazyInnerClassSingleton getInstance(){
        return LazyHolder.SINGLETON;
    }
}

以上三种写法,推荐使用静态内部类实现的单例,既在写法上比较优雅,又因为静态内部类是在系统用到时被加载,由JVM保证在唯一,所以是线程安全的

枚举类实现单例模式

public enum EnumSingleton {

    /**
     * 示例单例模式
     */
    SINGLETON;
    public Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }


    /**
     * 利用枚举实现单例模式
     *  线程绝对安全
     */
    public static EnumSingleton singleton() {
        return SINGLETON;
    }
}

懒汉式和饿汉式在一定程度上无法保证绝对的唯一,即使用反射可以获取到类的其他实例,而枚举类是由JVM保证的全局唯一,所以枚举类实现单例的方式是大多数推荐的写法

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 深蓝海洋 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读