设计模式之单例模式

2020-12-26  本文已影响0人  逍遥白亦

单例模式

定义

指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。

特点

  1. 单例类只有一个实例对象
  2. 该单例对象必须由单例类自行创建;
  3. 单例类对外提供一个访问该单例的全局访问点;

结构

主要角色

  1. 单例类:包含一个实例且能自行创建这个实例的类
  2. 访问类:使用单例的类

类图

实现

懒汉式单例

package Singleton;

/**
 * 懒汉式
 * 保证只有类在用到时才加载,注意线程安全
 * 由于加锁,性能会下降
 */
public class LazySingleton {

    private static volatile LazySingleton instance;

    private LazySingleton() {};

    public static synchronized LazySingleton getInstance(){
        if (instance == null){
            instance = new LazySingleton();
        }

        return instance;
    }

}

饿汉式单例

package Singleton;

/**
 * 饿汉式
 * 类加载到内存后,就实例化一个单例,JVM保证线程安全
 * 简单实用,推荐使用
 * 唯一缺点:不管用到与否,类加载时就完成实例化
 */
public class HungrySingleton {

    private static final HungrySingleton instance = new HungrySingleton();

    private HungrySingleton() {};

    public static HungrySingleton getInstance() {
        return instance;
    }

    public static void main(String[] args){
        HungrySingleton h1 = HungrySingleton.getInstance();
        HungrySingleton h2 = HungrySingleton.getInstance();
        System.out.println(h1 == h2);

    }

}

静态内部类实现

package Singleton;

/**
 * 静态内部类
 * JVM保证单例
 * 加载外部类时不会加载内部类,这样可以实现懒加载
 */
public class InnerStaticSingleton {

    private InnerStaticSingleton() {};

    private static class InnerStaticSingletonHolder{
        private static final InnerStaticSingleton INSTANCE = new InnerStaticSingleton();
    }

    public static InnerStaticSingleton getInstance(){
        return InnerStaticSingletonHolder.INSTANCE;
    }

    public static void main(String[] args){
        for (int i=0; i<100; i++){
            new Thread( () -> System.out.println(InnerStaticSingleton.getInstance().hashCode())).start();
        }
    }

}

Java创始人推荐的写法

package Singleton;

/**
 * Java创始人之一在Effective in Java中的写法
 * 保证线程安全,也保证反序列化,因为枚举类没有构造方法,无法构造出实例
 */
public enum NBSingleton {

    INSTANCE;

    public static void main(String[] args){
        for (int i=0; i<100; i++){
            new Thread( () -> System.out.println(NBSingleton.INSTANCE.hashCode())).start();
        }
    }

}

上一篇下一篇

猜你喜欢

热点阅读