【设计模式】(四)--创建型模式--单例模式

单例模式的定义

Ensure a class has only one instance, and provide a global point of access to it.
确保一个类只有一个实例,能够对整个系统提供访问。

Java语言中实现单例通常有两种变现形式。

  • 饿汉式单例模式:类加载时,就进行对象实例化
  • 懒汉式单例模式:第一次引用类才进行对象实例化

饿汉式单例模式

一种简单的饿汉式单例模式如下
在这里插入图片描述

public class Singleton {
    private static Singleton _instance = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return _instance;
    }
}

类加载时_instance会被初始化,此时private Singleton()【私有构造方法】会被调用,Singleton类的唯一实例创建成功。因为私有构造方法,外界无法利用构造函数创建出实例。整个系统仅有一个Singleton类实例。因为private Singleton(),因此类不能被继承。

懒汉式单例模式

一种简单的懒汉单例模式
在这里插入图片描述

public class Singleton {
    private static Singleton _instance = null;

    private Singleton() {

    }
    synchronized public static Singleton getInstance() {
        if (_instance == null) {
            _instance = new Singleton();
        }

        return _instance;
    }
}

外界调用Singleton 类静态同步方式getInstance()方法,因为进行了同步,即使并发也仅会产生一个实例。

饿汉式与懒汉式的区别:

饿汉式 懒汉式
实例化阶段 类加载时实例化 第一次引用时实例化
资源利用效率
速度和反应时间

单例模式的优点

  1. 内存中仅有一个实例,节约资源。
  2. 不用频繁的创建和销毁对象,提高性能。
  3. 仅有一个实例形成全局唯一的访问点。
  4. 避免对资源的多重占用。

单例模式的缺点

  1. 拓展困难,构造方法私有,无法继承。
  2. 不利于测试,某些测试方式无法方便的创建单例实例来模拟测试
  3. 与单一职责原则冲突。(来给我拓展一下)

Java中其他生成单例的方式

使用Spring框架,Spring框架默认就是单例

双重校验锁

性能比直接方法上加同步好。进行了两次的判断,第一次是为了避免不必要进入同步块,第二次是为了进行同步,避免多线程问题。由于singleton=new Singleton()对象的创建在JVM中可能会进行重排序,在多线程访问下存在风险,使用volatile修饰signleton实例变量有效,解决该问题。

public class Singleton {
    private volatile static Singleton _instance = null;
    private Singleton() {
    }
    public static Singleton getInstance() {
        if (_instance == null) {
            synchronized (Singleton.class) {
                if (_instance == null) {
                    _instance = new Singleton();
                }
            }
        }
        return _instance;
    }
}

静态内部类

只有第一次调用getInstance方法时,虚拟机才加载 Inner 并初始化instance ,只有一个线程可以获得对象的初始化锁,其他线程无法进行初始化,保证对象的唯一性。目前此方式是所有单例模式中最推荐的模式

public class Singleton {
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    private Singleton() {
    }
    public static final Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

枚举

默认枚举实例的创建是线程安全的,并且在任何情况下都是单例

public enum Singleton {
    INSTANCE;
}
原创文章 29 获赞 41 访问量 955

猜你喜欢

转载自blog.csdn.net/lovesunren/article/details/105696427