基於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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM