前提
某一天巧合打开了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 { /** * 启用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); ...... 复制代码
小结
在阅读一些主流框架源码的时候,可以借鉴一些设计合理的方案应用到自身的日常开发中。
参考资料: