单例模式Singleton

单例模式定义

确保某个类只有一个实例,并且自行实例化并向整个系统提供这个实例。java

单例模式类图

类图说明

  • Client:高层客户类
  • Singleton:单例类

实现单例模式的要点

  • 构造函数不对外开放,通常为Private
  • 经过一个静态方法或枚举返回单例类对象
  • 确保单例类的对象有且只有一个,尤为在多线程环境下
  • 确保单例类对象在反序列化时不会从新构建对象

单例模式的实现方式

  • 饿汉:在声明时就初始化
    /** 
     * 饿汉单例 
     */
    public class MySingleton {
        // 饿汉单例,在声明时就初始化
        private static MySingleton ourInstance = new MySingleton();
    
        public static MySingleton getInstance() {
            return ourInstance;
        }
    
        private MySingleton() {
        }
    }
  • 懒汉:只有在使用时才会实例化,在必定程度上节省了资源;缺点是第一次加载时须要及时进行实例化,反应稍慢,最大的问题是每次调用getInstance都要进行同步,形成没必要要的同步开销。这种模式通常不建议采用。
    /**
     * 懒汉单例
     */
    public class MySingleton {
        private static MySingleton ourInstance;
        
        public static synchronized MySingleton getInstance() {
            // 懒汉单例,只有在使用才会实例化
            if (ourInstance == null) {
                ourInstance = new MySingleton();
            }
            return ourInstance;
        }
    
        private MySingleton() {
        }
    }
  • DCL:Double Check Lock。优势是既可以在须要时实例化单例,又能保证线程安全,且单例对象初始化后调用getInstance不进行同步锁。
    /**
     * Double Check Lock(DCL)
     */
    public class MySingleton {
        private static MySingleton ourInstance = null;
    
        private MySingleton() {};
    
        public static MySingleton getInstance() {
            // 避免没必要要的同步
            if (ourInstance == null) {
                synchronized (MySingleton.class) {
                    // 建立实例
                    if (ourInstance == null) {
                        ourInstance = new MySingleton();
                    }
                }
            }
            return ourInstance;
        }
    }
  • 静态内部类:当第一次加载Singleton类时并不会初始化,只有在第一次调用时才会初始化。所以,第一次调用getInstance方法会致使虚拟机加载SingleHolder类,这种方式不只可以确保线程安全,也能保证单例对象的惟一性,同时也延迟了单例实例化,因此这是推荐使用的单例模式实现方式
    /**
     * 静态内部类单例模式
     */
    public class MySingleton {
    
        private MySingleton() {};
    
        public static MySingleton getInstance() {
            return SingletonHolder.ourInstance;
        }
    
        /**
         * 静态内部类
         */
        private static class SingletonHolder {
            private static MySingleton ourInstance = new MySingleton();
        }
    }
  • 枚举单例:枚举单例是线程安全的,而且在任何状况下它都是一个单例。且没法经过反序列化获得对象。
    /**
     * 枚举单例
     */
    public enum SingletonEnum {
        INSTANCE;
        public void dosomething() {
            System.out.println("do sth.");
        }
    }
  • 使用容器实现单例
    /**
     * 使用容器实现单例模式
     */
    public class SingletonManager {
        private static Map<String, Object> objMap = new HashMap<>();
    
        private SingletonManager() {}
    
        public static void registerService(String key, Object instance) {
            if (!objMap.containsKey(key)) {
                objMap.put(key, instance);
            }
        }
    
        public static Object getService(String key) {
            return objMap.get(key);
        }
    }

Android中的应用:

getSystemService 经过容器实现单例 安全

http://www.javashuo.com/article/p-zctqbwua-ed.html多线程

相关文章
相关标签/搜索