【问题标题】:How to implement the state design pattern in a JPA domain model如何在 JPA 领域模型中实现状态设计模式
【发布时间】:2010-10-20 07:13:59
【问题描述】:

我想在 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 领域模型中实现状态设计模式?

【问题讨论】:

    标签: java jpa design-patterns aspectj


    【解决方案1】:

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

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

    1.1.0.RELEASE 提供了一种默认机制,通过persisting StateMachineContext 保持状态,以及使用persist recipe 的替代方案。

    现在指的是 JPA - 可以让实体侦听器在 postload (@Postload) 上初始化状态机,我认为这不是一条好路。

    【讨论】:

      【解决方案2】:

      作为推论,这种 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());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-23
        • 1970-01-01
        • 2015-02-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多