美文网首页
单例模式

单例模式

作者: 不鸟万峰 | 来源:发表于2016-08-16 01:20 被阅读31次

    单例模式的目的

    创建对象,确保对象的唯一性,在同一个系统中,对象只有一个实例.让类自己负责保存它的唯一实例,提供一个访问实例的方法.

    单例模式概述

    单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。

    要点

    • 类只能有一个实例
    • 类自己负责创建实例
    • 提供访问实例的方法

    实现分类

    • 饿汉式
    • 懒汉式

    饿汉式

    pulic class Singleton{
      //唯一实例
      private static Singleton instance = new Singleton();
    
      //只能由类自己负责创建实例
      private Singleton(){
    
      }
    
    }
    //外部访问实例的方法
    public static getInstance(){
      return instance;
    }
    

    从代码中可以看出,在定义静态变量的时候就实例化了单例类.在类加载的时候,静态方法会先加载,所以单例对象在类加载的时候九被创建了,静态变量只加载一次,可以保证单例对象的唯一性,并且是线程安全的.但是在类加载的时候就创建,会影响程序的效率.

    懒汉式

    public class Singleton{
      //唯一实例
      private static Singleton instance = null;
    
      //只能由类自己负责创建实例
      private Singleton(){
    
      }
    
      //外部访问实例的方法
      public static getInstance(){
        if (interface  == null)
            instance = new Singleton();
        }
        return instance;
      }    
    }
    
    

    懒汉式在需要的时候才实例化,在类加载的时候不进行实例化,能起到懒加载的作用,但是如果在多线程的情况下,比如线程A和线程B同时调用getInstance(),可能会导致并发问题,所以要在getInstance()前加上synchronized进行同步,但是这样每次都要判断,会降低访问速度.可以用双重检查锁.
    双重检查锁的第一次检查是检查实例是否存在,如果不存在再进入下面的同步块,而不是直接进入同步块.第二重检查是进入同步块后,再检查实例是否存在,如果不存在,就在同步的情况下创景实例.

    /**
    *双重检查锁的单例模式
    */
    
    public class Singleton{
      /**
        * 对保存实例的变量添加volitile的修饰
        * 唯一实例
      */
      private volatile static Singleton instance = null;
    
      //只能由类自己负责创建实例
      private Singleton(){
    
      }
    
      //外部访问实例的方法
      public static getInstance(){
        //第一重检查,检查实例是否存在,如果不存在,再进入同步代码块
        if (interface  == null)
            //锁定代码块
            synchronized (Singleton.class){
              //第二重检查
              if (instance == null) {
                    instance = new Singleton();//创建单例实例
              }
            }
        }
        return instance;
      }    
    }
    
    

    更好的实现方式

    饿汉单例模式在类加载的时候就会创建,不能实现延时加载,如果以后不用,还会占据内存,还会影响程序的加载效率.懒汉单例模式需确保线程安全,性能会受到影响.比较好的实现方式是结合二者的优点,使用静态内部类来实现单例模式.

    public class Singleton {
    
        /**
         * 类级的内部类,也就是静态类的成员式内部类,
        *该内部类的实例与外部类的实例没有绑定关系,而且只有被调用时才会装载,从而实现了延迟加载
         */
         private static class SingletonHolder{
            /**
             * 静态初始化器,由JVM来保证线程安全
             */
            private static Singleton instance = new Singleton();
        }
    
        /**
         * 私有化构造方法
         * 只能由类自己负责创建实例
         */
        private Singleton(){
    
        }
    
        public static Singleton getInstance(){
            return SingletonHolder.instance;
        }
    }
    
    

    使用静态内部类,能实现延时加载,保证线程安全,又不影响系统性能.

    枚举类型实现

    根据<Effective Java>第二版,单元素的枚举类型已经成为实现Singleton的最佳方法。

    /**
     * 使用枚举来实现单例模式
     *
     */
    public class Singleton {
    
        /**
         * 定义一个枚举的元素,它就代表了Singleton的一个实例
         */
        uniqueInstance;
    
        /**
         * 单例的方法
         */
        public void singletonOperation(){
            //功能树立
        }
    }
    
    

    单例的使用场景

    系统只需要要一个实例对象,而且客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。

    相关文章

      网友评论

          本文标题:单例模式

          本文链接:https://www.haomeiwen.com/subject/suqpsttx.html