单例模式

  1. 懒汉式
    package com.bedrock.makemoney.designpattern.singletonmode.instance;
    
    import org.jetbrains.annotations.Contract;
    
    /*
    懒汉式,顾名思义就是实例在用到的时候才去创建,“比较懒”,用的时候才去检查有没有实例,如果有则返回,没有则新建。
    有线程安全和线程不安全两种写法,区别就是synchronized关键字。
     */
    public class LazyMan
    {
    
        private static LazyMan instance;
    
        @Contract(pure = true)//不要改变对象的状态的约定,默认为false
        private LazyMan() { }
    
        public static LazyMan getInstance()
        {
            if (instance == null)
            {
                instance = new LazyMan();
            }
            return instance;
        }
    }
  2. 饿汉式
    package com.bedrock.makemoney.designpattern.singletonmode.instance;
    
    import org.jetbrains.annotations.Contract;
    
    /*
    饿汉式,从名字上也很好理解,就是“比较勤”,实例在初始化的时候就已经建好了,不管你有没有用到,都先建好了再说。
    好处是没有线程安全的问题,坏处是浪费内存空间。
     */
    public class HungryMan
    {
        private static HungryMan instance = new HungryMan();
    
        @Contract(pure = true)
        public static HungryMan getInstance()
        {
            return instance;
        }
    }
  3. 双检锁
    package com.bedrock.makemoney.designpattern.singletonmode.instance;
    
    import org.jetbrains.annotations.Contract;
    
    /*
    双检锁,又叫双重校验锁,综合了懒汉式和饿汉式两者的优缺点整合而成。
    看下面代码实现中,特点是在synchronized关键字内外都加了一层 if 条件判断,这样既保证了线程安全,又比直接上锁提高了执行效率,还节省了内存空间。
     */
    public class DoubleCheckLock
    {
        private static DoubleCheckLock instance;
    
        @Contract(pure = true)
        private DoubleCheckLock(){ }
    
        public static DoubleCheckLock getInstance()
        {
            if (instance == null)
            {
                synchronized (DoubleCheckLock.class)
                {
                    if (instance == null)
                    {
                        instance = new DoubleCheckLock();
                    }
                }
            }
            return instance;
        }
    }
  4. 静态内部类
    package com.bedrock.makemoney.designpattern.singletonmode.instance;
    
    import org.jetbrains.annotations.Contract;
    
    /*
    静态内部类的方式效果类似双检锁,但实现更简单。
    但这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用
     */
    public class StaticInnerClass
    {
        private static class StaticInnerClassHolder
        {
            private static final StaticInnerClass INSTANCE = new StaticInnerClass();
        }
    
        @Contract(pure = true)
        private StaticInnerClass(){ }
    
        @Contract(pure = true)
        public static StaticInnerClass getInstance()
        {
            return StaticInnerClassHolder.INSTANCE;
        }
    }
  5. 枚举
    package com.bedrock.makemoney.designpattern.singletonmode.instance;
    
    import java.util.Hashtable;
    
    /*
    枚举的方式是比较少见的一种实现方式,但是看上面的代码实现,却更简洁清晰。
    并且她还自动支持序列化机制,绝对防止多次实例化
     */
    public enum EnumSingleton
    {
        INSTANCE;
    
        public void doSomething()
        {
            System.out.println("EnumSingleton: doSomething");
        }
    }

     

  6. 项目中的实际应用:我们项目是用的懒汉式,我在这里试了试枚举
    package com.bedrock.makemoney.designpattern.singletonmode.projectcase.bean;
    
    public class SystemPropertyDetail
    {
        private String activeFlag;
    
        private String propertyCode;
    
        private String propertyDesc;
    
        private String propertyValue;
    
        public String getActiveFlag()
        {
            return activeFlag;
        }
    
        public void setActiveFlag(String activeFlag)
        {
            this.activeFlag = activeFlag;
        }
    
        public String getPropertyCode()
        {
            return propertyCode;
        }
    
        public void setPropertyCode(String propertyCode)
        {
            this.propertyCode = propertyCode;
        }
    
        public String getPropertyDesc()
        {
            return propertyDesc;
        }
    
        public void setPropertyDesc(String propertyDesc)
        {
            this.propertyDesc = propertyDesc;
        }
    
        public String getPropertyValue()
        {
            return propertyValue;
        }
    
        public void setPropertyValue(String propertyValue)
        {
            this.propertyValue = propertyValue;
        }
    }
    package com.bedrock.makemoney.designpattern.singletonmode.projectcase.cache;
    
    import com.bedrock.makemoney.designpattern.singletonmode.projectcase.bean.SystemPropertyDetail;
    import org.jetbrains.annotations.Contract;
    import org.jetbrains.annotations.Nullable;
    
    import java.util.Collection;
    import java.util.Hashtable;
    
    public enum SystemPropertyCache
    {
        INSTANCE;
    
        private Hashtable<String, SystemPropertyDetail> systemPropertyHash = null;
    
        public void populate(Collection<SystemPropertyDetail> systemPropertyList)
        {
            Hashtable<String, SystemPropertyDetail> newSystemPropertyHash = new Hashtable<>();
    
            if (systemPropertyList != null)
            {
                for (Object object:systemPropertyList)
                {
                    SystemPropertyDetail systemPropertyDetail = (SystemPropertyDetail) object;
                    if (systemPropertyDetail !=null)
                    {
                        newSystemPropertyHash.put(systemPropertyDetail.getPropertyCode(),systemPropertyDetail);
                    }
                }
            }
    
            this.systemPropertyHash = newSystemPropertyHash;
        }
    
        @Contract("null -> null")
        private SystemPropertyDetail lookup(String propertyCode)
        {
            if (propertyCode != null)
            {
                return systemPropertyHash.get(propertyCode);
            }
            return null;
        }
    
        @Nullable
        public SystemPropertyDetail getSystemPropertyDetail(String propertyCode)
        {
            SystemPropertyDetail systemPropertyDetail = lookup(propertyCode);
            if (systemPropertyDetail != null)
            {
                SystemPropertyDetail newSystemPropertyDetail = new SystemPropertyDetail();
                newSystemPropertyDetail.setActiveFlag(systemPropertyDetail.getActiveFlag());
                newSystemPropertyDetail.setPropertyCode(systemPropertyDetail.getPropertyCode());
                newSystemPropertyDetail.setPropertyDesc(systemPropertyDetail.getPropertyDesc());
                newSystemPropertyDetail.setPropertyValue(systemPropertyDetail.getPropertyValue());
    
                return newSystemPropertyDetail;
            }
            return  null;
        }
    
        @Nullable
        public String getPropertyValue(String propertyCode)
        {
            SystemPropertyDetail systemPropertyDetail = lookup(propertyCode);
            if (systemPropertyDetail != null)
            {
                return systemPropertyDetail.getPropertyValue();
            }
            return  null;
        }
    }
    package com.bedrock.makemoney.designpattern.singletonmode.projectcase.test;
    
    import com.bedrock.makemoney.designpattern.singletonmode.projectcase.cache.SystemPropertyCache;
    import com.bedrock.makemoney.designpattern.singletonmode.projectcase.bean.SystemPropertyDetail;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Objects;
    
    public class ProjectCaseTest
    {
        public static void main(String[] args)
        {
            Collection<SystemPropertyDetail> collection = new ArrayList<>();
            //项目中从DB读取,在server启动的时候加载
            SystemPropertyDetail systemPropertyDetail = new SystemPropertyDetail();
            systemPropertyDetail.setActiveFlag("A");
            systemPropertyDetail.setPropertyCode("EXC");
            systemPropertyDetail.setPropertyDesc("Enable XXX Check");
            systemPropertyDetail.setPropertyValue("Y");
            collection.add(systemPropertyDetail);
    
            SystemPropertyCache.INSTANCE.populate(collection);
    
            System.out.println(Objects.requireNonNull(SystemPropertyCache.INSTANCE.getSystemPropertyDetail("EXC")).getPropertyValue());
            System.out.println(SystemPropertyCache.INSTANCE.getPropertyValue("EXC"));
    
            if ("Y".equals(SystemPropertyCache.INSTANCE.getPropertyValue("EXC")))
            {
                System.out.println("====开关打开时,才做某些业务====");
            }
    
        }
    }

     

posted @ 2021-12-07 21:18  bed_rock  阅读(190)  评论(0)    收藏  举报