单例模式

作者: 降龙_伏虎 | 来源:发表于2019-06-19 10:46 被阅读0次

    单例模式(Singleton Pattern)

    是指确保一个类在任何情况下都绝对只有一个实例
    私有化构造方法,属于创建型模式(结构型模式/行为型模式)
    

    1.饿汉式单例

    不管使用使用到,在类加载是进行创建
    缺点:浪费空间
    
    public class HungrySingleton{
        //私有静态不可覆盖变量
        private static final HungrySingleton hungrySingleton; 
        
        //类加载时创建类实例
        static{
            hungrySingleton = new HungrySingleton();
        }
        
        //私有化构造方法
        private HungrySingleton(){}
        
        //静态获取实例方法
        public static HungrySingleton getInstace(){
            return hungrySingleton;
        }
    }
    

    2.懒汉式单例

    类加载是并不初始化,第一次使用时进行初始化
    
    public class LazySingleton{
        //私有静态变量,默认为空
        private static  LazySingleton lazySingleton=null; 
        
        //私有化构造方法
        private HungrySingleton(){}
        
        //静态获取实例方法,线程不安全实例可能会多次被创建
        public static LazySingleton getInstace(){
            if(lazySingleton == null){
                lazySingleton = new lazySingleton();
            }
            return lazySingleton;
        }
    }
    

    3.注册式单例

    即:内部类模式单例(性能最优)
    
    public class LazyInnerClassSingleton{
    
        //私有化构造方法
        private LazyInnerClassSingleton(){
            //防止反射破解
            if(LazyHolder.LAZY != null){
                throw new Exception("不允许构建多个实例");
            }
        }
        
        //静态获取实例方法,线程安全
        //①懒汉式加载
        //②LazyHoler中的逻辑,当getInstace被调用时候才知晓
        //③巧妙的运用了内部类的特性,JVM底层逻辑.完美的避免了线程安全问题
        public static fianl LazyInnerClassSingleton getInstace(){
           return LazyHolder.LAZY;
        }
        //防止序列化->反序列化对象破解单例
        private Object readResolve(){
            return LazyHolder.LAZY
        }
        
        //内部类
        private static  class LazyHolder{
            private static  final LazyInnerClassSingleton LAZY = new LazyInnerClassSingleton();
        }
    }
    
    //反射破解
    public class Test{
        public static void main(String[] args0){
            try{
                Class<?> clazz = LazyInnerClassSingleton.class;
                java.lang.reflect.Conotructor c = clazz.getDeclaredConotructor(null);
                c.setAccessible(true);
                c.newInstance();
            }catch(Exception e){
                e.printStackTrace();
            }
    
        }   
    }
    

    3.1枚举式(注册式的一种)

    /**
     * Description:数据库连接(被单例对象)
     *
     * @date 2019-05-09 16:23
     */
    
    public class DBConnection {
    }
    
    /**
     * Description:数据源枚举
     *
     * @date 2019-05-09 16:10
     */
    
    public enum DataSourceEnum {
    
        DATASOURCE;
    
        private DBConnection dbConnection;
    
        public DBConnection getDbConnection() {
            return dbConnection;
        }
    
        public static DataSourceEnum getInstance(){
            return DATASOURCE;
        }
    
        DataSourceEnum() {
            this.dbConnection = new DBConnection();
        }
    }
    
    /**
     * Description:测试
     *
     * @date 2019-05-09 16:14
     */
    
    public class Test {
        public static void main(String[] args) {
            DBConnection con1 = DataSourceEnum.DATASOURCE.getDbConnection();
            DBConnection con2 = DataSourceEnum.DATASOURCE.getDbConnection();
            System.out.println(con1 == con2);
        }
    }
    

    原理

    3.2容器式单例

    ① 私有化构造方法
    
    ②定义线程安全的容器(ConcurrentMap)
    
    ③获取对象时,先从容器内取,存在容器内直接返回;不出存在通过反射获取对象放入容器后进    行返回,注意线程安全问题,需要解决
    

    3.3.ThreadLocal单例

    伪线程安全:全局线程不安全,线程内线程安全
    
    public class Apple{
    
        private Apple(){}
        
        private static final ThreadLocal<Apple> threadLocalInstance = new ThreadLocal<Apple>(){
            @Override
            protected Apple initiaValue(){
                return new Apple();
            }
        }
        
        public static Apple getInstance(){
            threadLocalInstance.get();
        }
    }
    

    相关文章

      网友评论

        本文标题:单例模式

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