【问题标题】:How to convert my state machine to java?如何将我的状态机转换为 java?
【发布时间】:2011-07-23 17:43:42
【问题描述】:

这是我在 C++ 中做事的常规方式:

class object
{
public:
     enum
     {
          STATE_ACTIVE = 0,
          STATE_INACTIVE,

          OBJ_NUM_STATES,
     }

     int   m_State;

     virtual void  UpdateState  ()
     {
           switch(this->m_state)
           {
           case STATE_ACTIVE:    /* do stuff*/    break;
           case STATE_INACTIVE:  /* do stuff*/    break;
           }
     }
}

class SpecialGameObject : public Object
{
public:
    enum
    {
         STATE_SPECIAL_A = OBJ_NUM_STATES + 1,
         STATE_SPECIAL_B,

         SPECIAL_NUM_STATES,
    }

    virtual void UpdateState ()
    {
         Object::UpdateState();

         switch(this->m_State)
         {
         case STATE_ACTIVE:       /* do extra stuff */   break;
         case STATE_SPECIAL_A:    /* do special stuff*/  break;
         case STATE_SPECIAL_B:    /* do special stuff*/  break;
         }
    }
}

我试图弄清楚如何让所有这些功能在 java 中工作。具体来说,我需要工作:

1) 派生类具有自动排列在派生状态值之后的状态值的能力。这样我就可以向基类添加新的状态值,而不必担心它们会与任何派生类中使用的状态值重叠。

2) 能够在 switch 语句中使用状态值作为 case。

我研究了使用静态最终整数来实现我的状态值。但这些不能用作案例陈述。然后我研究了扩展枚举,但这是不允许的。

有人对我有什么建议吗?

谢谢

【问题讨论】:

    标签: java enums switch-statement state-machine extends


    【解决方案1】:

    您需要在 Java 中实现状态模式。这个might 帮助你。 Wikipedia还有一个简单易懂的Java例子。

    【讨论】:

      【解决方案2】:

      这足以让你继续前进吗?

      final class GameObject {
      
        enum State { ACTIVE, INACTIVE };
      
        State state;
      
        void updateState()
        {
          switch(state) {
            case ACTIVE :
              // update state
              break;
            case INACTIVE:
              // update STATE
              break;
            default:
              assert false : "never get here";
          }
        } 
      }
      

      请注意,在 Java 中,enums 是 final,因此您不能直接扩展枚举。 (Reference this SO question.) 如果你真的需要将状态的概念扩展到专门的子类,事情可能已经够复杂了,你应该考虑using polymorphism rather than switch statements (see also here) 来获得你想要的东西。或者,您可以将“超级”状态与包装器超类和子类中的专用子状态捆绑在一起,也许还有定义的接口。

      而且,如果你想严重扭曲,你可以做这样的事情。 Java 枚举可以实现接口非常酷,但我认为这是使用该功能解决您的问题的一种特别丑陋的方式......

      final class GameObject {
      
        ActiveStateful state;
      
        interface ActiveStateful {
          State activeState();
        }
      
        enum State implements ActiveStateful {
          ACTIVE, INACTIVE;
      
          public State activeState() {
            return this;
          }
        };
      
        enum SubState implements ActiveStateful {
          SPECIAL_A(State.ACTIVE), SPECIAL_B(State.ACTIVE);
      
          SubState(final State activeState) {
            this.activeState = activeState;
          }
      
          final State activeState;
      
          public State activeState() {
            return activeState;
          }
      
        }
      
      }
      

      【讨论】:

        【解决方案3】:

        但这些不能用作案例陈述。

        如果我告诉你这是不正确的,那会解决你的问题,是吗?这是不正确的:您可以打开静态 final int 常量。

        【讨论】:

          【解决方案4】:

          我建议对 switch 语句使用枚举及其序数值。这就是 enum 的诞生目的。

          【讨论】:

          • 你的意思是 ordinal 值而不是基数? (switch 并不真正需要它们,编译器内部除外。)
          【解决方案5】:

          请考虑完全摆脱switch。这是一种可怕的憎恶,几十年前就应该停止,但没有。阅读优秀的 “Abandoning switch In Three (And A Bit) Steps” 文章了解更多信息。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-03-27
            • 1970-01-01
            • 2017-04-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多