title: 位状态的使用 date: 2017.05.04 02:15 categories:
- 技术博客 tags:
- Web
- Java
Web项目中很常见的一种需求:即用户持有各种不同的状态。
这次使用到的是其中一种,即非开即合的情况,也就是同一状态只能有开和闭两种情况,比如用户有无绑定手机、用户是否实名认证、用户订单是否送达等等。
按照之前的做法,我一般是在用户信息持有类(如User
)中不停地加属性。比如isBindPhone
,isBindEmail
,项目初期还好说,可能也就五六个状态,再往后就是灾难,可能有二十个这种状态,再往后就不敢想了,所以得想个办法来保持User
的简洁可用。
前面已经提到了,这些状态都是非开即合,学过计算机的应该都能感觉到这东西应该用二进制来做,因为二进制不是0就是1,怎么用到这里来代替之前的做法呢?
答案是:位状态。
1.编写工具类
作用是封装所有状态的值以及操作,下面是代码片段。
public class BitStatesUtil {
public final static Long BIND_PHONE = 1L << 0; //用户是否绑定了邮箱
public final static Long BIND_EMAIL = 1L << 1; // 用户是否实名认证
/**
* @param states
* 所有状态值
* @param value
* 需要判断状态值
* @return 是否存在
*/
public static boolean hasState(long states, long value) {
return (states & value) != 0;
}
/**
* @param states
* 已有状态值
* @param value
* 需要添加状态值
* @return 新的状态值
*/
public static long addState(long states, long value) {
if (hasState(states, value)) {
return states;
}
return (states | value);
}
/**
* @param states
* 已有状态值
* @param value
* 需要删除状态值
* @return 新的状态值
*/
public static long removeState(long states, long value) {
if (!hasState(states, value)) {
return states;
}
return states ^ value;
}
}
复制代码
2.理解上面的设计
- 代码是否合适用过来,主要还是看业务需求。
- 不同状态的表示同样使用了数字,而在二进制下恰好只需要
<<1
来进行占位操作,增加新的状态时只需要在之前的基础上递增一位,示例中给出了两个状态。 - 数据类型的选择取决于自己项目中的需求,多就取大,少就取小,long类型64位已经可以代表64种。点这里回顾你大学就了解的数据类型知识点。
- 对不同状态的关系管理使用到了与或异或操作。点这里看他的解释。
- 一个缺点,代码用起来可读性较差。