--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
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.
When you're done, press ** Copy to Clipboard ** to copy the code and paste it into your IDE or editor.
The following are examples of generating various Builder patterns.
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.
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();
}
}
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();
}
}
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;
}
}
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=[])
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.
--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'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<>());
}
--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 ~)
--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)
--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.