1.1.C-Singleton单例模式

定义:保证一个类有且仅有一个实例,并且自行实例化(无需手动new)向整个系统提供。
    通过单例模式可以保证系统内只会存在该类的一个实例,从而方便了对实例数量的控制和系统资源的节约。如果希望在系统中,某个类的实例只存在一个,那单例模式是最好的解决方案。所谓一山不能容二虎,一夫不能有二妻,就是这个道理。
单例模式要素:
    1.私有构造方法
    2.私有静态引用指向自己实例
    3.以自己实例为返回值的公有静态方法
使用场景:
    1.要求生成唯一序列号的环境
    2.在整个项目中需要一个共享访问点或共享数据,例如一个Web页面上的计数器,可以不用把每次刷新都记录到数据库中,使用单例模式保持计数器的值,并确保是线程安全的
    3.创建一个对象需要消耗的资源过多,如要访问IO和数据库等资源
    4.需要定义大量的静态常量和静态方法(如工具类)的环境,可以采用单例模式(当然,也可以直接声明为static的方式)
    5.配合配置信息进行使用,例如将配置信息放入一个properties文件中,利用一个单例可以获取该文件中的各项配置内容

 

单例模式又称为单子模式或singleton模式。singleton模式又分为两种:懒汉式和饿汉式。
懒汉式
/**
 * 单例模式-懒汉式
 *
 * @auth zhangjingxuan
 * @since 2018年4月11日上午9:47:50
 */
public class Singleton2 {
 
    //1.创建类的唯一实例,使用private static修饰
    private static Singleton2 instance;
   
    //2.将构造方式私有化,不允许外边直接创建对象
    private Singleton2() {
        System.out.println("Singleton2初始化完毕");
    }
   
    //3.提供一个用于获取实例的方法,使用public static修饰
    public static Singleton2 getInstance(){
        if(instance==null){
            instance=new Singleton2();
        }
        return instance;
    }
   
    //4.其他方法尽可能使用static进行修饰
    public static void doSomething() {
        System.out.println("Singleton2 doSomething");
    }
}
 
 
饿汉式
/**
 * 单例模式-饿汉式
 *
 * @auth zhangjingxuan
 * @since 2018年4月11日上午9:45:30
 */
public class Singleton1 {
 
    //1.创建类的唯一实例,使用private static修饰
    private static Singleton1 instance = new Singleton1();
   
    //2.将构造方式私有化,不允许外边直接创建对象
    private Singleton1() {
        System.out.println("Singleton1初始化完毕");
    }
   
    //3.提供一个用于获取实例的方法,使用public static修饰
    public static Singleton1 getInstance(){
        return instance;
    }
   
    //4.其他方法尽可能使用static进行修饰
    public static void doSomething() {
        System.out.println("Singleton1 doSomething");
    }
}
 
 
测试
public class Test {
 
    public static void main(String[] args) {
        Singleton1.doSomething();
       
        Singleton2.doSomething();
    }
}
 
 
结果
Singleton1初始化完毕
Singleton1 doSomething
Singleton2 doSomething
 
 
懒汉式vs饿汉式
    1.在编码上主要区别是上述代码的第一步,是否需要在getInstance()之前进行实例化
    2.懒汉式的特点是加载类的时候比较快,但运行时获取实例时比较慢,线程不安全
    3.饿汉式的特点是加载类的时候比较慢(需要实例化),但运行时获取实例(getInstance())时比较快,线程安全
    4.懒汉式不获取实例而直接调用doSomething时,不会实例化操作
    5.饿汉式不获取实例而直接调用doSomething时,依然进行实例化操作
 
综上可知,懒汉模式是线程安全的,但在某些场景下会浪费系统资源。饿汉模式是线程不安全的,但相对懒汉模式会节约系统资源。所以,如果能有一种包含单例特点、线程安全和节约系统资源三种特点为一身的写法该有多好!程序界有一句话是“只要你能想到,我们就能给你做到”,因此这种奢华的写法也出现了。
 
线程安全&节约资源的单例模式(懒汉式+线程锁)
/**
 * 单例模式-懒汉式
 *
 * @auth zhangjingxuan
 * @since 2018年4月11日上午9:47:50
 */
public class Singleton3 {
 
    //1.防止利用反射调用单例,从而破坏单例模式的flag(在构造函数中会用到)
    private static boolean initialized = false;
 
    //2.静态的内部类(寄生虫),解决多线程安全问题
    private static class LazyHolder {
        private static final Singleton3 instance = new Singleton3();
    }
   
    //3.构造函数(配合initialized使用)
    private Singleton3() {
        //解决反射破坏到单例
        synchronized (Singleton3.class) {
            if (!initialized) {
                initialized = true;
                System.out.println("Singleton3初始化完毕");
            } else {
                throw new RuntimeException("禁止初始化...");
            }
        }
    }
 
    //4.提供一个用于获取实例的方法,使用public static修饰
    public static Singleton3 getInstance() {
        return LazyHolder.instance;
    }
   
    public static void doSomething() {
        System.out.println("Singleton3 doSomething");
    }
}
 
 感谢以下博客达人,摘要文献来自以下:

 

猜你喜欢

转载自waxuanxuan.iteye.com/blog/2418292
今日推荐