国家模式实施困难

时间:2014-01-18 19:19:56

标签: java design-patterns architecture

我在我的应用程序中使用state pattern,因为我的state-entities具有API,其行为因当前状态而发生变化。

在我的情况下,依赖于状态的API仅由一个方法组成 - changeState。此方法更改状态并执行一些与状态相关的逻辑。

但有一种情况让我问这个问题:状态依赖逻辑不仅取决于当前状态,还取决于newState(见下面的代码)。所以我必须使用instanceof

问题: 摆脱instanceof 的真正方法是什么?

public interface IStateEntity {
  void changeState(IState newState);
}

public interface IState {
  void doStateDependentLogic(IState newState);
}

public class StateEntityImpl {

  private IState state;

  @Override
  public void changeState(IState newState) {
    state.doStateDependentLogic(newState);
    state = newState;  
  }
}

public class StateImplA { //each state implementation is a singleton

  @Override
  public void doStateDependentLogic(IState newState) {
      // HARDSHIP #1: state dependent logic depends not only on current state, but also it depends on newState. So I have to use `instanceof`
     if (newState instanceof StateImplA) {
       //do one logic
     } else if (newState instanceof StateImplB) {
       //do another logic
     }
  }
}

编辑(为什么不枚举):

如果枚举替换getClass().getSimpleName():因为它是函数式编程范例。当我以依赖className的方式构建我的架构时,第一个迹象表明出现了问题。对我来说,将instanceof更改为enum并不意味着改变架构,而只是改变一个坏事。

如果将每个IState实现作为枚举:每个IState实现都是Hibernate实体。

2 个答案:

答案 0 :(得分:2)

Java在Java中创建单例的方法是enum。这提供了线程安全的初始化以及JVM保证的单例状态。创建class的第二个实例的方法有很多,而不是enum

使用enum的额外好处是,您可以在逻辑中enum开启案例:

public enum State {

    STATE_A {
        @Override
        public void doStateDependentLogic(final State newState) {
            switch (newState) {
                case STATE_B:
                    //do stuff
                //case SOME_OTHER_STATE
            }
        }
    },
    STATE_B {
        @Override
        public void doStateDependentLogic(final State newState) {
        }
    };

    public abstract void doStateDependentLogic(State newState);
}

我不知道你在哪里认为enum函数式编程范例。不是这种情况。 Java中的enum旨在完全按照您的意愿执行。

答案 1 :(得分:1)

你的问题不是状态模式。问题出在状态模式完成之后,就是将方法调用路由到表示状态的某个实现。

子类的instanceof问题是一个独立的问题。这里的解决方案是避免在其他代码中使用instanceof,最好通过方法在状态和下一个状态之间进行交互。超过switch类型的enum已经看起来更好但是并没有好多,因为您仍然依赖于另一个对象的具体类型。可以认为是好的,因为所有这些都是在同一个类中定义的,因此依赖性只取决于你自己。

在最好的情况下你最终应该看起来像

  @Override
  public void doStateDependentLogic(IState newState) {
     if (newState.isBeautiful()) {
         System.out.println(newState.getYourPartOfTheInterAction(this));
     } else {
         somethingElse();
     }
  }

即。方法调用抽象而不关心实现细节。