jeudi 23 septembre 2021

Java abstract Step Builder pattern

I am designing a java system where users can define some rules in a fluent style.

Rules have many properties, which are partly mutually exclusive. We use a builder pattern with validation for this.

To make the system easier to use, we want to introduce a StepBuilder, to guide the user to all necessary steps.

There are different types of rules, but all share some common properties.

Current System:

abstract BaseBuilder<T extends BaseBuilder<T>> {

   protected String property1;
   protected String property2;
   protected String property3;

   abstract Rule build();

   public T withProperty1(String data) { 
      this.property1 = data; 
      return this; 
   }

   public T withProperty2(String data) { 
       this.property2 = data; 
       return this; 
   }

   public T withProperty3(String data) { 
       //this should only be possible if property2 is not set or similar logic
       this.property3 = data; 
       return this; 
   }
}

//there are a few others like this e.g. SpecialBuilder1-10
class SpecialRuleBuilder extends BaseBuilder<SpecialBuilder> {

       protected String special1;
       protected String special2;

       public T withSpecial1(String data) { 
          this.special1 = data; 
          return this; 
       }

       public T withSpecial2(String data) { 
           this.special2 = data; 
           return this; 
       }

     @Override
     Rule builder() {
        return new SpecialRule(property1, property3, special1, special2, ....);
     }

     static SpecialRuleBuilder builder() {
        return new SpecialRuleBuilder();
     }
    
}

class BuilderTest() {
   
   //User can set anything, no steps are enforced at compile time
   Result result = SpecialBuilder.builder()
                        .property1("some")
                        .special2("thing")
                        .build(); 

}

How can we use a StepBuilder including a hierarchy (parent class), so the user cannot get to the same step twice. Ideally the user should not be aware of all the special builders and have the same entry point and guided steps. For example:

Result result = GeneralBuilder.builder()
                              .withBaseProperty1("asdas") <-- Step 1
                              .withBaseProperty2("asd")  <-- Step 2, Step 3 is now not visible, continue with all possible special options
                              .withSpecial1("asd") <-- no we are in the step of one concrete builder, and should not get "out" again, not even to the base methods

I know how to define the interface steps, I just dont know how to include all possible starting steps of the special builders at the end of the base steps, since the higher interface/class should probably not rely on the lower parts of the hierarchy.

Is this somehow possible?

Aucun commentaire:

Enregistrer un commentaire