People worry, people make, Builder patterns-Tools that automatically generate Java Builder patterns-

Overview

--We have created and released a tool ** that can automatically generate the Java source code of one of the design patterns "** Builder pattern **" on the ** Web . - Effective Java **, ** GoF **, ** Telescoping Constructor **, ** Lombok ** Instantly generate each Builder pattern

How to use

The app is as follows

https://riversun.github.io/java-builder/

(I don't use the server because it is made only with HTML / CSS / JS)

As shown below, if you enumerate "** type variable name **" in Definition, it will be reflected in ** real time ** in the code on the right. animation.gif

When you're done, press ** Copy to Clipboard ** to copy the code and paste it into your IDE or editor.

Generated code example

The following are examples of generating various Builder patterns.

Original data (Definition) entered

The following is the content entered to generate code (class name, type, variable name, etc.)

If you enter ** type name ** in the text area in Definition and enumerate with line breaks as shown below, the code will be automatically generated on the right side in real time.

package org.example
class Person
@NotNull String name
int age
String sex
List<String> hobby

** @ </ span> NotNull ** If you put the annotation at the beginning of the definition line, that property will be a required property and will generate code to check for null during build.

Generated Effective Java Builder pattern

Person.java(Automatically generated by the tool)


package org.example;
import java.util.ArrayList;
import java.util.List;

public class Person {

  private String name;
  private int age;
  private String sex;
  private List<String> hobby;

  public static class Builder {
    
    private String name;
    private int age;
    private String sex;
    private List<String> hobby = new ArrayList<String>();

    public Builder() {    
    }
      
    Builder(String name, int age, String sex, List<String> hobby) {    
      this.name = name; 
      this.age = age; 
      this.sex = sex; 
      this.hobby = hobby;             
    }
        
    public Builder name(String name){
      this.name = name;
      return Builder.this;
    }

    public Builder age(int age){
      this.age = age;
      return Builder.this;
    }

    public Builder sex(String sex){
      this.sex = sex;
      return Builder.this;
    }

    public Builder hobby(List<String> hobby){
      this.hobby = hobby;
      return Builder.this;
    }

    public Builder addHobby(String hobby){
      this.hobby.add(hobby);
      return Builder.this;
    }

    public Person build() {
        if(this.name == null){
          throw new NullPointerException("The property \"name\" is null. "
              + "Please set the value by \"name()\". "
              + "The property \"name\" is required.");
        }

        return new Person(this);
    }
  }

  private Person(Builder builder) {
    this.name = builder.name; 
    this.age = builder.age; 
    this.sex = builder.sex; 
    this.hobby = builder.hobby;     
  }

  public void doSomething() {
      // do something
  }
}

When using it, do it like this

AppMain.java


public class AppMain {
	public static void main(String[] args) {
		new Person.Builder()
		.name("Tom")
		.age(18)
		.sex("male")
		.addHobby("programming")
		.addHobby("skiing")
		.build().doSomething();
	}
}

Generated GoF Builder pattern

The GoF Builder pattern has a few more characters and multiple classes are generated. It also generates ** AppMain.java **, which is the main equivalent. The main edit will be ** Director.java **, which determines the actual Build conditions.

Person.java(Automatically generated)


package org.example;
import java.util.ArrayList;
import java.util.List;

public class Person {

  private String name;
  private int age;
  private String sex;
  private List<String> hobby = new ArrayList<String>();

  public Person() {

  }

  public Person(String name, int age, String sex, List<String> hobby) {
    this.name = name; 
    this.age = age; 
    this.sex = sex; 
    this.hobby = hobby; 
  }

  public Person setName(String name){
    this.name = name;
    return Person.this;
  }

  public String getName(){
    return this.name;
  }

  public Person setAge(int age){
    this.age = age;
    return Person.this;
  }

  public int getAge(){
    return this.age;
  }

  public Person setSex(String sex){
    this.sex = sex;
    return Person.this;
  }

  public String getSex(){
    return this.sex;
  }

  public Person setHobby(List<String> hobby){
    this.hobby = hobby;
    return Person.this;
  }

  public Person addHobby(String hobby){
    this.hobby.add(hobby);
    return Person.this;
  }

  public List<String> getHobby(){
    return this.hobby;
  }

  public void doSomething(){
    System.out.println("Person's properties");
    System.out.println("name="+name);
    System.out.println("age="+age);
    System.out.println("sex="+sex);
    System.out.println("hobby="+hobby);  
  }
}

Builder.java(Automatically generated)


package org.example;
import java.util.List;

public interface Builder {

  public void name(String name);
  public void age(int age);
  public void sex(String sex);
  public void hobby(List<String> hobby);

  Person getResult();
}

PersonBuilder.java(Automatically generated)


package org.example;
import java.util.List;

public class PersonBuilder implements Builder {
  private Person person;

  public PersonBuilder() {
    this.person = new Person();
  }

  @Override
  public void name(String name) {
    this.person.setName(name);
  }

  @Override
  public void age(int age) {
    this.person.setAge(age);
  }

  @Override
  public void sex(String sex) {
    this.person.setSex(sex);
  }

  @Override
  public void hobby(List<String> hobby) {
    this.person.setHobby(hobby);
  }


  @Override
  public Person getResult() {
  
    if(this.person.getName() == null){
      throw new NullPointerException("The property \"name\" is null. "
          + "Please set the value by \"builder.name()\" at Director class. "
          + "The property \"name\" is required.");
    }

    return this.person;
  }
}

Director.java(Automatically generated)


package org.example;

public class Director {

  private Builder builder;

  public Director(Builder builder) {
    this.builder = builder;
  }

  public void construct() {
    builder.name("something"); // required property
    builder.age(0); // optional property
    builder.sex("something"); // optional property
    //builder.hobby(new ArrayList<>());
  }
}

AppMain.java(Automatically generated)


package org.example;

public class AppMain {
  
  public static void main(String[] args) {
    
    Builder builder = new PersonBuilder();
    Director director = new Director(builder);
    director.construct();
    Person person = builder.getResult();
    person.doSomething();
    
  }
}

Generated Telescoping Constructor

I don't think it's a ** Builder pattern **, but it's a very common pattern that takes multiple arguments to the constructor when creating an object.

(As the number of arguments increases, the outlook gets worse, so the ** Builder pattern ** comes into play.)

Person.java


package org.example;
import java.util.ArrayList;
import java.util.List;

public class Person {

  private String name;
  private int age;
  private String sex;
  private List<String> hobby = new ArrayList<String>();

  public Person() {

  }

  public Person(String name, int age, String sex, List<String> hobby) {
    this.name = name; 
    this.age = age; 
    this.sex = sex; 
    this.hobby = hobby; 
  }

  public Person setName(String name) {
    this.name = name;
    return Person.this;
  }

  public String getName() {
    return this.name;
  }

  public Person setAge(int age) {
    this.age = age;
    return Person.this;
  }

  public int getAge() {
    return this.age;
  }

  public Person setSex(String sex) {
    this.sex = sex;
    return Person.this;
  }

  public String getSex() {
    return this.sex;
  }

  public Person setHobby(List<String> hobby) {
    this.hobby = hobby;
    return Person.this;
  }

  public Person addHobby(String hobby){
    this.hobby.add(hobby);
    return Person.this;
  }

  public List<String> getHobby() {
    return this.hobby;
  }

}

Generated Lombok Builder pattern

With this tool, you can generate the same code that is automatically generated when you annotate Lombok with ** @ </ span> Builder **.

Person.java(Automatically generated)


package org.example;
import java.util.ArrayList;
import java.util.List;

public class Person {

  private String name;
  private int age;
  private String sex;
  private List<String> hobby;

  Person(String name, int age, String sex, List<String> hobby) {
  
    if(name == null){
      throw new NullPointerException("The property \"name\" is null. "
          + "Please set the value by \"name()\". "
          + "The property \"name\" is required.");
    }

    this.name = name; 
    this.age = age; 
    this.sex = sex; 
    this.hobby = hobby; 
  }
  
  public static PersonBuilder builder(){
    return new PersonBuilder();
  }  
  public static class PersonBuilder {
    
    private String name;
    private int age;
    private String sex;
    private List<String> hobby = new ArrayList<String>();

    PersonBuilder() {    
    }
      
    public PersonBuilder name(String name){
      this.name = name;
      return PersonBuilder.this;
    }

    public PersonBuilder age(int age){
      this.age = age;
      return PersonBuilder.this;
    }

    public PersonBuilder sex(String sex){
      this.sex = sex;
      return PersonBuilder.this;
    }

    public PersonBuilder hobby(List<String> hobby){
      this.hobby = hobby;
      return PersonBuilder.this;
    }

    public PersonBuilder addHobby(String hobby){
      this.hobby.add(hobby);
      return PersonBuilder.this;
    }

    public Person build() {
      return new Person(this.name, this.age, this.sex, this.hobby);
    }
    @Override
    public String toString() {
      return "Person.PersonBuilder(name=" + this.name + ", age=" + this.age + ", sex=" + this.sex + ", hobby=" + this.hobby + ")";
    }
  }
  
  @Override
  public String toString() {
    return "Person(name=" + this.name + ", age=" + this.age + ", sex=" + this.sex + ", hobby=" + this.hobby + ")";
  }
  
  public void doSomething() {
      // do something
  }
}

When using the Lombok Builder pattern, do something like this

AppMain.java


public class AppMain {
    public static void main(String[] args) {
        System.out.println(Person.builder().name("Tom").age(12).sex("male").build());
    }
}

Execution result

Person(name=Tom, age=12, sex=male, hobby=[])

Automatically generated point memo

The following measures have been taken with the aim of producing typical code output so that the generated code can be used as it is without making detailed generation settings.

** Effective Java Template **

--In the case of ** List <> ** like List <String> hobby;, initialization with new ArrayList (); and like ```add Hobby (String hobby) `` I also created a method that allows you to add items individually. -Null check code is not generated for primitive type variables such as ** int **.

** GoF template **

--GoF's Builder pattern is more complicated to build objects than others, so I made it generate `ʻAppMain.java(main class). -** Temporary code is now generated in the construct`` method of Director.java **.

  public void construct() {
    builder.name("something");
    builder.age(0);
    builder.sex("something");
    //builder.hobby(new ArrayList<>());
  }

** Telescoping Constructor template **

--The Setter method now allows method chain invocations like Person setName (name) instead of void setName (name) like the original Java Beans.

(There is still room for improvement ~)

Summary

--We have created and published a web tool that allows you to easily generate Java code for the Builder pattern. ――I hope it helps you. ――It seems that there are some plug-ins in IntelliJ and Eclipse that can generate Builder patterns by using Lombok. (I'm a self-made tool lover, so it's fun to make)

(bonus)

--Since Java code is generated, I thought about making it in Java short-circuited and made https://github.com/riversun/java-builder-pattern-source-generator, but the code design was left as it was from the middle Changed to Web version (JavaScript). Basically, it is generated by a simple template match.

Recommended Posts

People worry, people make, Builder patterns-Tools that automatically generate Java Builder patterns-
Automatically generate Loto 6 purchase plans with Java that super beginners have learned