zoukankan      html  css  js  c++  java
  • 基于BIT数组实现全局功能开关

    前提

    某一天巧合打开了sofa-bolt项目,查找部分源码,看到了项目中使用bit数组实现功能开关的特性,感觉这种方式可以借鉴,于是写下这篇文章。

    原理

    bit数组的布局如下:

    由于每个bit都可以表示1或者0,刚好对应于开关的ONOFF。只需要定义好每个开关所在的bit数组下标和开关的状态(ON = 1或者OFF = 0),通过判断不同开关下标所在的bit即可判断开关的状态:

    • 优点:节省空间,理论上只需要占用最多2n位的内存(n为开关的数量,这里考虑扩容,扩容让bit数组长度为原来的2倍)
    • 缺点:暂时没发现

    实现

    JDK中的bit数组可以直接使用BitSet。首先定义开关定义SwitchDef

    public class SwitchConst {
    
        public static final boolean ON = true;
        public static final boolean OFF = false;
    }
    
    @RequiredArgsConstructor
    @Getter
    public enum SwitchDef {
    
        /**
         * 启用HTTPS
         */
        ENABLE_HTTPS(0, SwitchConst.ON, "启用HTTPS"),
    
        /**
         * 启用异步
         */
        ENABLE_ASYNC(1, SwitchConst.OFF, "启用异步"),
    
        ;
    
        /**
         * 下标
         */
        private final int index;
    
        /**
         * 默认状态
         */
        private final boolean defaultStatus;
    
        /**
         * 描述
         */
        private final String description;
    
        @Override
        public String toString() {
            return String.format("SwitchDef(name=%s,description=%s)", name(), description);
        }
    }
    

    接着定义开关接口Switch

    public interface Switch {
    
        /**
         * 启用
         *
         * @param switchDef switchDef
         */
        void turnOn(SwitchDef switchDef);
    
        /**
         * 关闭
         *
         * @param switchDef switchDef
         */
        void turnOff(SwitchDef switchDef);
    
        /**
         * 判断状态
         *
         * @param switchDef switchDef
         * @return boolean
         */
        boolean status(SwitchDef switchDef);
    }
    

    最后编写开关实现BitSetSwitch和客户端代码:

    public enum BitSetSwitch implements Switch {
    
        /**
         * 单例
         */
        X;
    
        BitSetSwitch() {
            init();
        }
    
        private final BitSet switches = new BitSet();
    
        @Override
        public void turnOn(SwitchDef switchDef) {
            switches.set(switchDef.getIndex(), SwitchConst.ON);
        }
    
        @Override
        public void turnOff(SwitchDef switchDef) {
            switches.clear(switchDef.getIndex());
        }
    
        @Override
        public boolean status(SwitchDef switchDef) {
            return switches.get(switchDef.getIndex());
        }
    
        private void init() {
            Stream.of(SwitchDef.values()).forEach(item -> switches.set(item.getIndex(), item.isDefaultStatus()));
        }
    
        public static void main(String[] args) {
            Switch s = BitSetSwitch.X;
            s.turnOn(SwitchDef.ENABLE_HTTPS);
            s.turnOff(SwitchDef.ENABLE_ASYNC);
            System.out.printf("开关[%s],状态:%s%n", SwitchDef.ENABLE_HTTPS, s.status(SwitchDef.ENABLE_HTTPS));
            System.out.printf("开关[%s],状态:%s%n", SwitchDef.ENABLE_ASYNC, s.status(SwitchDef.ENABLE_ASYNC));
        }
    }
    

    执行该main方法后控制台输出如下:

    开关[SwitchDef(name=ENABLE_HTTPS,description=启用HTTPS)],状态:true
    开关[SwitchDef(name=ENABLE_ASYNC,description=启用异步)],状态:false
    

    仿真场景(伪代码)如下:

    Switch s = BitSetSwitch.X;
    String uri = "www.throwx.cn";
    String schema = "http";
    if (s.turnOn(SwitchDef.ENABLE_HTTPS)){
        schema = "https";
    }
    HttpClint ch = new DefaultHttpClient();
    if (s.turnOn(SwitchDef.ENABLE_ASYNC)){
        ch = new AsyncHttpClient();
    }
    Result r = ch.executeRequest(schema + uri);
    ......
    

    小结

    在阅读一些主流框架源码的时候,可以借鉴一些设计合理的方案应用到自身的日常开发中。

    参考资料:

    (e-a-20210724 c-2-d)

  • 相关阅读:
    Palindrome Partitioning
    Minimum Path Sum
    Maximum Depth of Binary Tree
    Minimum Depth of Binary Tree
    Unique Binary Search Trees II
    Unique Binary Search Trees
    Merge Intervals
    Merge Sorted Array
    Unique Paths II
    C++ Primer Plus 笔记第九章
  • 原文地址:https://www.cnblogs.com/throwable/p/15083516.html
Copyright © 2011-2022 走看看