前提 某一天巧合打开了sofa-bolt
项目,查找部分源码,看到了项目中使用bit
数组实现功能开关的特性,感觉这种方式可以借鉴,于是写下这篇文章。
原理 bit
数组的布局如下:
由于每个bit
都可以表示1
或者0
,刚好对应于开关的ON
和OFF
。只需要定义好每个开关所在的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 { 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 { void turnOn (SwitchDef switchDef) ; void turnOff (SwitchDef switchDef) ; 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); ......
小结 在阅读一些主流框架源码的时候,可以借鉴一些设计合理的方案应用到自身的日常开发中。
参考资料: