持久化具有许多布尔属性的对象的状态

时间:2012-04-05 20:59:50

标签: state state-machine

对于简单对象,通常很容易拥有一个“state”属性,该属性是一个字符串并可存储在数据库中。例如,想象一个User类。它可能处于非活动状态,未经验证状态和活动状态。这个可以跟踪两个布尔值 - “活动”和“已验证” - 但它也可以使用简单的状态机从非活动状态转换为未验证状态到活动状态,同时将当前状态存储在该状态“属性。很常见,对吧?

然而,现在假设一个类有更多布尔属性,更重要的是,它可以有很多组合。例如,可能被破坏,丢失,停用,过时等的事物。现在,在单个“状态”属性中跟踪状态变得更加困难。我想这是一个非确定性有限自动机或状态机。我真的不想存储“inactive_broken”和“active_missing_outdated”等状态。

我提出的最好的方法是同时拥有“状态”属性并存储某种超级状态 - “可用”与“不可用”,在这种情况下 - 每个属性布尔值。这样我在过渡时可以采用类似守卫的方法。

还有其他人遇到过这个问题,并提出了一个跟踪状态的好解决方案吗?

3 个答案:

答案 0 :(得分:1)

您是否考虑将“状态”序列化为位掩码并将其存储在数据库的整数列中?假设一个实体可以是活动的或不活动的,可用的或不可用的,或者以任何组合工作或破坏。

您可以将每个州存储一下;无论是开还是关。这样,值111将是活动的,可用的和可用的,而值000将是不活动的,不可用的和破坏的。

然后,您可以使用适当的位掩码查询特定组合,或者将实体反序列化为具有您想要跟踪的每个状态的布尔值的类。将状态添加到对象并且不会破坏已经序列化的对象也是相对便宜的。

答案 1 :(得分:1)

与上述答案相同,但比理论更实用:

  • 确定可能的布尔属性数。所有这些属性的状态可以表示为1 = true或0 = false

  • 采用适当大小的数值数据类型。 unsigned short = 16,unsigned int = 32,unsigned long = 64,如果你有一个更大的类型,则取一个数组:例如128个属性需要

    unsigned long[] attr= new long[2];  // two long side by side
    
  • 可以使用以下代码访问每个位

    bool GetBitAt(long attr, int position){
        return (attr & (1<<(position-1)) >0;
    }
    long SetBitAt(long attr, int position, bool value){
        return attr|=1<<(position-1);
    }
    
  • 现在让每个位位置代表一个属性。例如:第5位意味着可用吗?

     bool IsAvailable(long attr){
          return GetBitAt(attr, 5);
     }
    

好处

  • 节省空间,例如64个属性只需要8个字节。

  • 轻松保存和阅读您只需阅读短片,整数或长片,这只是一个简单的变量

  • 比较一组属性很简单,因为您可以简单地将short,int或long的数值与另一个进行比较。例如if(Obj.attributes == Obj2.attributes){}

答案 2 :(得分:0)

我认为你正在描述Orthogonal Regions的一个例子。从该链接,&#34;正交区域解决了当系统的行为被分割成独立的,同时活动的部分时,状态数量组合增加的常见问题。&#34;

您可以通过对象组合实现此方法。例如,您的超级对象包含多个子对象。每个子对象彼此独立地保持它们的相关状态。超级对象的状态是其所有子对象状态的组合。

搜索&#34;正交状态&#34;,&#34;正交区域&#34;或&#34;正交分量&#34;更多的想法。

相关问题