如何在JPA域模型中实现状态设计模式

时间:2010-10-20 07:14:00

标签: java design-patterns jpa

我想在JPA中实现状态设计模式。我目前正在执行此操作的方式在此blog post中列出。

作者使用包含所有可用状态实现的枚举,而不是为状态抽象创建抽象类/接口,并为每个状态编写实现。我发现这种方法非常有用,因为枚举可以在JPA中轻松序列化,您可以无需额外的努力即可存储对象的当前状态。我还将状态接口和所有状态类嵌套到枚举中,使它们成为私有的,因为它们是特定于实现的,并且不应该对任何客户端可见。这是枚举的代码示例:

public enum State {

  STATE_A(new StateA()),
  STATE_B(new StateB());

  private final StateTransition state;

  private State(StateTransition state) {
     this.state = state;
  }

  void transitionA(Context ctx) {
    state.transitionA(ctx);
  }

  void transitionB(Context ctx) {
     state.transitionB(ctx);
  }

  private interface StateTransition {

    void transitionA(Context ctx);

    void transitionB(Context ctx);
  }

  private static class StateA implements StateTransition {

    @Override
    public void transitionA(Context ctx) {
        // do something
    ctx.setState(STATE_B);
    }

    @Override
    public void transitionB(Context ctx) {
        // do something
    ctx.setState(STATE_A);
    }
  }

  private static class StateB implements StateTransition {

    @Override
    public void transitionA(Context ctx) {
    throw new IllegalStateException("transition not allowed");
    }

    @Override
    public void transitionB(Context ctx) {
        // do something
    ctx.setState(STATE_A);
    }
  }
}

我想和你分享这些并了解你的想法。你觉得这有用吗?您将如何在JPA域模型中实现状态设计模式?

感谢, 西奥

2 个答案:

答案 0 :(得分:0)

这是一个老问题,但是为了那些可能搜索档案的人 - 我使用了弹簧状态机和枚举(而不是字符串)。

关于处理转换,有一些注释允许在转换发生时调用函数。

1.1.0.RELEASE提供了一种默认机制,可以按persisting StateMachineContext保持状态,另一种使用persist recipe

现在引用JPA - 可以使用实体监听器来初始化postload(@Postload)上的状态机,我认为这不是好路。

答案 1 :(得分:0)

作为一个必然结果,将AspectJ模式与特定于常量的Enum类结合使用也很有用。我这里没有展示Spring集成,因为它只关注AspectJ。但是我想我们也可以将Spring和AspectJ一起使用。

还有一点是,OO模式在此用例中可能功能强大。我之所以显示这种模式,仅仅是因为问题指向博客帖子,该博客帖子具有指向Spring和AspectJ示例的链接。

我还需要在JPA中使用良好的OO模式。

public interface StateTransition {

StateTransition activate();

StateTransition deActivate();

}
  
public enum AStateTransition implements StateTransition{

ACTIVATE(new Activation()),

DEACTIVATE(new DeActivation());

private final StateTransition stateTransition;

private AStateTransition(StateTransition stateTransition) {
    this.stateTransition = stateTransition;
}

@Override
public StateTransition activate() {
    return stateTransition.activate();
}

@Override
public StateTransition deActivate() {
    return stateTransition.deActivate();
}
}

public class Activation implements StateTransition {

@Override
public StateTransition activate() {
    return AStateTransition.ACTIVATE;
}

@Override
public StateTransition deActivate() {
    return AStateTransition.DEACTIVATE;
}
}

public class DeActivation implements StateTransition {

@Override
public StateTransition deActivate() {
    return AStateTransition.DEACTIVATE;
}

@Override
public StateTransition activate() {
    return AStateTransition.ACTIVATE;
}
}

 @Aspect()


 public class StateChangeAspect {

    //Could be more generic so that all implemented methods
    //are covered
    @Pointcut("execution(* AStateTransition.activate()) && target(stateTransition) && if()")

    public static boolean stateChangePointcut( AStateTransition stateTransition ){
        return AStateTransition.ACTIVATE == stateTransition;
    }

    @Before("stateChangePointcut(stateTransition)")
    public void test1( AStateTransition stateTransition ) {
        System.out.println( " aspect  " );
    }

    @Before("stateChangePointcut(stateTransition)")
    public void test1(JoinPoint joinPoint, AStateTransition stateTransition) {
      System.out.println(joinPoint + " -> " + stateTransition);
    }

}

测试代码:

        System.out.println(AStateTransition.ACTIVATE.activate());
        System.out.println(AStateTransition.DEACTIVATE.deActivate());