The introduction

Nuwa made people 🤏, may first knead a head, and then knead a hand, and then knead a foot; Maybe a foot, then a head, then a hand. The order is variable, the components are all the same, and out could be an old man, a man, a woman, and so on.

The definition of the builder pattern is also understood in this way, separating the construction of a complex object from its representation, so that the same construction process can create different representations, the definition is very fancy, you can refer to the above example of Nuwa made people, you can quickly understand.

Usage scenarios

If an object has a complex internal structure, and you want to separate the creation and use of complex objects. More specifically, consider using the constructor pattern when a class has more than four constructor arguments, some of which are optional.

The advantages of the Builder mode are also obvious, such as good encapsulation, separation of creation and use, good expansion, independence between each Builder class and decoupling to a certain extent. The disadvantage is that redundant Builder objects will be generated when the product is used. Once changes occur inside the product, it will cost a lot for the Builder to modify

Coding

So let’s do a simple example of cooking, and here’s a simple example of cooking, where you have to use spices and food, so let’s rewrite the toString method so that we can print

public class Dishes {

    /** * Seasoning */
    private String condiment;

    /** ** main material */
    private String food;

    @Override
    public String toString(a) {
        return "Dishes{" + "condiment='" + condiment + '\' ' + ", food='" + food + '\' ' + '} '; }}Copy the code

We need an inner class to implement the seasoning and food that goes into our pot

    /** * static inner class */
    public static class FoodBuilder {

        /** * Seasoning */
        private String condiment;

        /** ** main material */
        private String food;

        public FoodBuilder buildCondiment(String condiment) {
            this.condiment = condiment;
            return this;
        }

        public FoodBuilder buildFood(String food) {
            this.food = food;
            return this;
        }

        public Dishes build(a) {
            return new Dishes(this); }}Copy the code

The important thing to note here is that our buildCondiment, buildFood is a chain call, so we return the FoodBuilder class, and we need a build method at the end to get our dish out

Finally, implement a constructor to pass in our FoodBuilder

    private Dishes(FoodBuilder foodBuilder) {
        /** * Seasoning */
        this.condiment = foodBuilder.condiment;
        /** ** main material */
        this.food = foodBuilder.food;
    }
Copy the code

You’re done

public class Dishes {

    /** * Seasoning */
    private String condiment;

    /** ** main material */
    private String food;

    @Override
    public String toString(a) {
        return "Dishes{" + "condiment='" + condiment + '\' ' + ", food='" + food + '\' ' + '} ';
    }

    private Dishes(FoodBuilder foodBuilder) {
        /** * Seasoning */
        this.condiment = foodBuilder.condiment;
        /** ** main material */
        this.food = foodBuilder.food;
    }

    /** * static inner class */
    public static class FoodBuilder {

        /** * Seasoning */
        private String condiment;

        /** ** main material */
        private String food;

        public FoodBuilder buildCondiment(String condiment) {
            this.condiment = condiment;
            return this;
        }

        public FoodBuilder buildFood(String food) {
            this.food = food;
            return this;
        }

        public Dishes build(a) {
            return new Dishes(this); }}}Copy the code

Rather than stay up all night for code, don’t let bug points be submitted and develop a good single test to get up

public class Test {
    public static void main(String[] args) {
        Dishes dishes = new Dishes.FoodBuilder().buildFood("Pork").buildCondiment("Pepper").build();
        System.out.println(dishes);
    }
}

Dishes{condiment='pepper', food='pork'}

Process finished with exit code 0
Copy the code

Ok, it’s very nice, the chili meat is done

Framework using

The Builder pattern is very widely used in frameworks, lombok and StringBulider, which we use a lot, are practices of the Builder pattern

lombok

@Data
@Builder
public class User {
 
    private Long id;
 
    private String name;
}

public class TestLombok {
    public static void main(String[] args) {
        
        User user = User.builder().id(1L).build(); System.out.println(user); }}Copy the code

StringBulider

StringBulider is also a very classic implementation of the Builder pattern, and we can focus on lines 129-138

    @Override
    public StringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }

    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
Copy the code

We can clearly see that the AppEnd method returns the StringBuilder class

Of course, there are many frames where the builder pattern is hidden

The Builder pattern in Spring has

  • BeanDefinitionBuilder
  • UriComponents

The Mybatis

  • SqlSessionFactoryBuilder
  • Example object generated by Mybatis Gennerator

Everyone can go to 🧐

So that’s the end of this issue. With caution, I’m Skow

Give it a thumbs up before you go, and I’ll see you next time