15

如何优雅地运用位运算实现产品需求

 3 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzA5NDg3MjAwMQ%3D%3D&%3Bmid=2457105590&%3Bidx=1&%3Bsn=2e22805709c0c9fe1049fcf108cb6cd4
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

点击上方“ 服务端思维 ”,选择“ 设为星标

回复” 669 “获取独家整理的精选资料集

回复” 加群 “加入全国服务端高端社群「后端圈」

IZz63mE.jpg!web

作者 | 梁桂钊

出品 | 服务端思维

在开始正文之前,我们先来说一下 Linux 的系统权限设计。在 Linux 系统中,为了保证文件的安全,对文件所有者、同组用户、其他用户的访问权限进行了分别管理。其中,文件所有者,即建立文件或目录的用户。同组用户,是所属组群中的所有用户。其他用户,指的是既不是文件所有者,也不是同组用户的其他用户。每个文件和目录都具有读取权限、写入权限和执行权限,这三个权限之间相互独立。

Qfiiiy3.png!web

在 Linux 系统中,每个文件的访问权限可以用 9 个字母表示,每 3 个字母表示一类用户权限,分别代表文件创建者、同组用户、其他用户。其中,r 表示读取权限,w 表示写入权限,x 表示执行权限。通过功能模式修改文件权限,有三个部分组成,包括对象、操作和权限。

UFf2eaU.png!web

假设需要增加同组用户写入权限,下面来看一个例子。

此外,每一类用户的访问也可以通过数字的方式进行表示。

AzYbAny.png!web

那么,通过数字模式就可以对常见的 Linux 文件权限操作进行归纳。

JRjiU3Y.png!web

假设需要设置创建者可读可写可执行、同组用户可读、其他用户可读,我们可以这样写:

事实上,Linux 的文件访问权限就是非常经典的位运算使用场景。无独有偶,我们再来看下 Java 中的 java.lang.reflect.Modifier 。其中, Modifier 类采用 16 进制定义了静态常量。 

aEZf2a7.png!web

紧接着, Modifier 类提供了很多静态方法,例如 isPublic() 方法的返回值 &PUBLIC 对应的 16 进制值,如果非 0,则说明含有 public 修饰符。

qEruuuF.png!web

这里有一个重要的知 识点,采用 & 运算,两位同时为 1,结果才为 1,否则为 0。 即 0&0=0; 0&1=0; 1&0=0; 1&1=1。 例如: 3&1  即 0000 0 011 & 0000 0001 = 00000001,值为 1。

QbyEjaI.png!web

与此同时, Modifier 类还采用 | 运算,确保参加运算的两个对象只要有一个为 1,其值为 1。即 0|0=0;0|1=1;1|0=1;1|1=1。例如 Modifier.PUBLIC | Modifier.PROTECTED  | Modifier.PRIVATE | Modifier.ABSTRACT       | Modifier.STATIC | Modifier.FINAL | Modifier.STRICT 的结果是 3103,即 110000011111。

uUr6Rjy.png!web

书归正传,我们站在前辈们的肩上,通过位运算设计优雅的多选标识,例如通过位运算实现权限控制或多状态管理,它的好处在于易扩展,避免数据库设计过程中字段膨胀,减少磁盘存储空间。

假设,我们现在有一个有一个业务需求:在任务中添加一个通知方式,可选项包括 IM 消息、系统提醒、邮箱、短信。选择 IM 消息后,支持 IM 即时发送;选择系统提醒后,支持站内信推送;选择选择邮箱后,该任务后续相关提醒内容,可通过发送邮件至相关人邮箱中进行通知;选择短信后,该任务后续相关提醒内容,可通过发送短信至相关人进行通知。

uqmMri2.png!web 我们在设计数据库库表时,通常情况下,将多个标识字段合并成一个字段,并把这个字段改成字符串型方式保存,例如,存在 1 时表示支持 IM,2 时表示支持系统消息,3 表示支持邮箱,4 表示支持短信。此时,如果同时都满足,它的存储形式就是以逗号分隔的字符串:“1,2,3,4”。这样设计的好处在于,不仅消除相同字段的冗余,而且当增加新的渠道类别时,不需增加新的字段。

JFnQniA.png!web

但在数据查询时,我们需要对字符串进行分隔。并且字符串类型的字段在查询效率和存储空间上不如整型字段。因此,我们可以用“位”来解决这个问题。我们采取不同的位来分别表示不同类别的标识字段。

a2qaaev.png!web

因此,当某个任务支持 IM 时,则保存 1(0000 0001);支持系统消息时,则保存 2(0000 0010),支持邮箱时,则保存 4(0000 0100);支持短信时,则保存 8(0000 1000)。四种都支持,则保存 15 (0000 11111)。

yY36faU.png!web

紧接着,我们通过封装常用方法来实现增删改。

v2MFZjY.png!web

— 新书出版 —

新书出版

zUzMFvU.jpg!web

YRvEJzy.jpg!web

— 知识星球 —

加入「面试研习社」星球,心动不如行动,目前优惠活动: 早鸟用户(现价 79¥/年, 原价 99 ¥/年

  • 早鸟用户将享受推广期限时折扣,请及时关注当前的最新优惠活动。

  • 支持 3 天无理由退款。

  • 优惠在 7 月 17 日晚 20:00 整开放,持续一周。

    UfEzmuI.png!web

— 本文结束 —

漫谈设计模式在 Spring 框架中的良好实践

颠覆微服务认知: 深入思考微服务的七个主流观点

人人都是 API 设计者

一文讲透微服务下如何保证事务的一致性

要黑盒测试微服务内部服务间调用,我该如何实现?

JfqmQvI.png!web

关注我,回复 「加群」 加入各种主题讨论群。

对「服务端思维」有期待,请在文末点个 在看

喜欢这篇文章,欢迎 转发、分享 朋友圈

在看点这里

M7vyQ3Q.gif

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK