【问题标题】:Building fluent APIs in Java to build testdata for database用 Java 构建流利的 API 来为数据库构建测试数据
【发布时间】:2015-08-29 00:38:44
【问题描述】:

我正在尝试用 Java 制作一个小型 DSL,我可以用它来填充数据库中的测试数据。我想使用的语言如下。

createRowInTableA().
   createRowInTableB().
createRowInTableA().
   createRowInTableB().
      createRowInTableC().
end();

创建表的顺序很重要,例如 tableB 依赖于 tableA,tableC 依赖于 tableA 和 tableB。因此,我想使创建 tableB 的选项在创建 tableA 等之后直接可用。我已经开始创建描述 DSL 的接口,但我不知道我应该如何实际实现接口以使我正在寻找的嵌套行为类型。这就是界面的样子。

public interface End {
    public void sendTestData(); 
}

public interface TableA extends End {
   public Builder createRowInTableA();
}

public interface TableB extends TableA {
   public Builder createRowInTableB();
}

public interface TableC extends TableB {
   public Builder createRowInTableC();
}

但是,当我开始使用构建器模式来实现这种语言以创建流畅的 API 时,我想要的层次结构消失了。

public class DBBuilder implements TableC {
   static class Builder {
      public Builder createRowInTableA(){...}
      public Builder createRowInTableB(){...}
      public Builder createRowInTableC(){...}
   }
}

【问题讨论】:

  • 你可以有很多构建器类,每个类都有一组有限的方法;并且一个方法可能会返回另一个构建器类型。这可能会变得太复杂,而且可能不值得。

标签: java dsl builder fluent


【解决方案1】:

您可以使用一组接口和类适配器:

public interface canCreateTableAIf{
   public DBBuilderB createRowInTableA()
}  

public interface canCreateTableBIf{
   public DBBuilderC createRowInTableB()
}  

public interface canCreateTableCIf{
   public DBBuilderD createRowInTableC()
}  


public class canCreateTableA implements canCreateTableAIf (){
  public DBBuilderB createRowInTableA(){
    ...
  }
}

public class canCreateTableB implements canCreateTableBIf (){
  public DBBuilderC createRowInTableB(){
    ...
  }
}

public class DBBuilderRoot extends canCreateTableA {
}


public class DBBuilderB  extends canCreateTableB {
}

public class DBBuilderBCD  extends canCreateTableB,canCreateTablec,canCreateTableD {
}

【讨论】:

    【解决方案2】:

    这并不复杂。但我会检查是否有比使用 fluent Builders 更好的方法。例如,Java 8 提供了闭包。 Hier 是我的建议。我还没有编译和测试它。这个想法应该可行,但可能存在语法错误。

    public class ABuilder 
    {
        private BBuilder subBuilder;
    
        public ABuilder()
        {
          subBuilder = new BBuilder(this);
        }
    
        public BBuilder createRowForA()
        {
           // your code
           return this.subBuilder;
        }
    
        public void end()
        {
          // send test data
        }
    }
    

    x

    public class BBuilder 
    {
        private ABuilder parentBuilder;
        private CBuilder subBuilder;
    
        public BBuilder( ABuilder parentBuilder )
        {
          this.parentBuilder = parentBuilder;
          this.subBuilder = new CBuilder(this);
        }
    
        public CBuilder createRowForB()
        {
           // your code
           return this.subBuilder;
        }
    
        public ABuilder end()
        {
          return this.parentBuilder;
        }
    }
    

    x

    public class CBuilder 
    {
        private BBuilder parentBuilder;
    
        public CBuilder( BBuilder parentBuilder )
        {
          this.parentBuilder = parentBuilder;
        }
    
        public CBuilder createRowForC()
        {
           // your code
    
           // I Assume you want to be able to write more than 1 C-row
           return this;
        }
    
        public BBuilder end()
        {
          return this.parentBuilder;
        }
    }
    

    那么你可以这样做:

    (new ABuilder())
        .createRowForA()
          .createRowForB()
            .createRowForC()
            .end()
          .end()
         .end();
    
    (new ABuilder())
        .createRowForA()
          .createRowForB()
            .end()
          .createRowForB()
            .createRowForC()
            .end()
           .end()
         .end();
    

    我相信您会看到更多示例。 ;-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多