當要用一個值儲存多種狀態的時候,可以利用bit flag。
bit flag是指利用一個數值的二進位表示的0和1來代表狀態的開啟或關閉、存在或不存在。
通常都是用boolean
來做flag。
boolean isVip; // true or false
但問題是boolean
只能表示兩種狀態,若有多種狀態,就必須要有多個boolean
變數來儲存。
而使用bit flag則只需要用一個數值變數即可儲存多種狀態。
Color.java
public class Color {
// 二進位表示
public static final int BLACK = 0b0001; // 1
public static final int WHITE = 0b0010; // 2
public static final int BLUE = 0b0100; // 4
public static final int RED = 0b1000; // 8
private int colors; // bit flag
public int getColors() {
return colors;
}
public void setColors(int colors) {
this.colors = colors;
}
/** 是否有顏色 */
public boolean hasColors() {
return colors != 0;
}
/** 加入顏色 */
public void addColors(int color) {
colors |= color;
}
/** 移除顏色 */
public void removeColors(int color) {
colors &= ~color;
}
/** 是否為同顏色 */
public boolean isColors(int colorMask) {
return colors == colorMask;
}
/** 是否包含顏色 */
public boolean isContainColors(int colorMask) {
return (colors & colorMask) != 0;
}
/** 是否不包含顏色 */
public boolean isNotContainColors(int colorMask) {
return (colors & colorMask) == 0;
}
}
上面的Color.colors
即是big flag,可儲存多種顏色,並搭配位元遮罩bit mask即上面的colorMask
及位元運算子來做各種操作。
public static void main(String[] args) {
Color c = new Color();
int colors = Color.BLUE;
c.setColors(colors); // colors is BLUE
System.out.println(c.isColors(Color.BLUE)); // true
System.out.println(c.isContainColors(Color.RED | Color.BLUE)); // true
c.addColors(Color.RED); // now colors is BLUE and RED
System.out.println(c.isContainColors(Color.RED)); // true
c.removeColors(Color.BLUE); // now colors is RED
System.out.println(c.isContainColors(Color.BLUE)); // false
c.addColors(Color.BLACK | Color.WHITE); // now colors is RED, BLACK, WHITE
System.out.println(c.isContainColors(Color.WHITE)); // true
c.removeColors(Color.RED | Color.BLACK | Color.WHITE);
System.out.println(c.hasColors()); // false
c.setColors(Color.WHITE | Color.BLACK); // now color is WHITE and BLACK
System.out.println(c.isNotContainColors(Color.RED)); // true
System.out.println(c.isNotContainColors(Color.RED | Color.WHITE)); // false
}
之前在某工作的產品也是這樣設計,該產品前端畫面有許多功能面板,而面板中又有許多功能,其透過在資料庫設定flag值來控制功能的開啟或關閉。系統啟動後會先去資料庫撈取flag的值,然後與應用層設定的各mask值做判斷來決定前端某功能的開啟或關閉。然而資料庫欄位使用bit flag儲存多種狀態的設計會讓程式變得難維護。例如在資料庫的設定功能的欄位`features`的值為33,很難知道這個值所代表的意思,即使有良好的文件說明仍要計算才能知道。
看了些文章big flag可以改用EnumSet<E extends Enum<E>>
來實作。
如果本篇有幫助到您,幫忙點一下廣告支持,感恩。
沒有留言:
張貼留言