This is the third day of my participation in the August More text Challenge. For details, see:August is more challenging

Welcome to today’s lesson. Today we’re going to talk about the Nagging builder pattern. A few more words, I mentioned earlier that this month will be on Java design patterns in detail, welcome to click on the profile picture, follow my column, I will continue to update, come on!

Series of articles:

Singletons of design patterns

The factory model of design pattern

. Series of continuous updates

Without further ado, let’s get to the point

Builder mode

The Builder pattern is another frequently used creative design pattern — often called Builder pattern, or Builder pattern or generator pattern in Chinese.

So today we’re going to change our strategy, and we’re going to start by not talking about principles, but we’re going to start with examples, and we’re going to look for answers in problem solving cases. The kind of answer you think.

Let’s take a look at what the builder mode mainly brings or solves:

  • Is it inconvenient to use the constructor or set method to create the object? Is there an easy way to create objects

  • Why is the builder pattern needed to create objects

Below through the code specific in-depth understanding, we only talk about dry goods, let you see the end can solve the actual problems in your code now!

Scenario and case sharing

For the same scenario we compare the code with builder mode and without builder mode:

Quite simply, we create the student object


/** * Student entities * do not use builder mode */
public class Students {
    private String name;    / / name
    private int age;        / / age
    private String grade;   / / class
    private String gender;  / / gender
    public Student(String name, int age, String grade, String gender) {
        this.name = name;
        this.age = age;
        this.grade = grade;
        this.gender = gender;
    }
    public Student(String name, int age, String grade) {
        this.name = name;
        this.age = age;
        this.grade = grade;
    }
    public Student(String name, int age) {
        this.name = name;
        this.age = age; }}// The above code writes constructors with three different arguments
public static void main(String[] args) {
    Student student01 = new Student("Zhang".26."13 class"."Male");
    
    Student student02 = new Student("Zhang".26."13 class"); . }Copy the code

Any questions about that? No questions. Is this code okay? What do you think? The problem is obvious (and I’m sure there are plenty of people who do this at work). The above code does not use the builder pattern, so we need to use the traditional getter and setter methods and specify different input parameters to construct the object. If there are too many parameters and too many businesses, you need to create too many constructors.

Using builder mode, however, the function of the class is completely different, as follows:


/** * Student entities ** Use builder mode to create objects */
public class Students {
    // All attributes
    private String name;   
    private int age;       
    private String grade;  
    private String gender; 
    
    public Students(a) {}// The internal Builder New object
    public static Students builder(a) {
        return new Students();
    }
    
    // Use attributes as steps
    public Students name(String name) {
        this.name = name;
        return this;
    }
    // Use attributes as steps
    public Students age(int age) {
        this.age = age;
        return this;
    }
    // Use attributes as steps
    public Students grade(String grade) {
        this.grade = grade;
        return this;
    }
    // Use attributes as steps
    public Students gender(String gender) {
        this.gender = gender;
        return this;
    }
    
    // Perform the create operation (last seal return)
    public Students build(a) {
        validateObject(this);
        return this;
    }
    private void validateObject(Students Students) {
        // You can do basic precheck or custom check
    }
    @Override
    public String toString(a) {
        return "Students{" +
                "name='" + name + '\' ' +
                ", age=" + age +
                ", grade='" + grade + '\' ' +
                ", gender='" + gender + '\' ' +
                '} '; }}// Use the builder pattern to create objects
public static void main(String[] args) {
    
    // Create an object
    Students st = Students.builder()
            .name("Zhang")
            .age("26")
            .grade("13 class")
            .gender("Male")
            .build();
            
      // Create an object
    Students st01 = Students.builder()
            .name("Zhang")
            .age("26")
            .grade("13 class")
            .build();       
            
     // Build each property step by step
}

Copy the code

This is the builder mode to get things done. We can see that completely different object instances are being built, and with traditional getter and setter methods, we need to write many different constructors to cope with the changes.

So, using the builder pattern makes it easier to instantiate objects on demand, avoid writing constructors with many different arguments, and overcome the disadvantage of writing only one constructor for the same type of argument.

Although the above example is simple to implement, it demonstrates how to use the builder pattern. In practical use, you can often implement the Builder pattern of the class itself directly using Lombok’s @Builder annotation

Why use the builder pattern to create objects? What is the meaning of existence

Why use the builder pattern to create classes? In my opinion, there are several reasons.

  • First, the multi-step attribute assignment is more suitable for multiple result class creation scenarios. In object-oriented software development, most of the time needed to create the class parameter is not a can be prepared, for example, to calculate the order preferential price, to track the status of inventory, etc., some parameters may need by calling multiple service operation to draw, then we can according to the known parameters in advance to create the class again when the appropriate parameters, such as setting the class attribute, Instead of waiting until all the results are ready to create a class.

  • Second, there is no need to care about the specific algorithm implementation of a particular type of builder. For example, when we use StringBuilder, we care less about its code implementation and more about the functionality it provides us. This can improve coding efficiency in some scenarios that require rapid reuse.

  • Third, improve the code’s readability, concise and clear, need which function (attribute), which call, easy to read, maintainable. The internal properties are highly extensible and freely combine object attributes.

  • Fourth, meet the open closed principle, which is also the advantage of the design pattern. Each builder is relatively independent, so it can easily be replaced or added, which greatly increases the extensibility of the code.

Of course, after praise, or to point out some of the objectivity of the existence of some problems.

  • Limited scope of use. The builder pattern generally creates objects that need to have a lot in common, and if object instances differ widely, the builder pattern is not appropriate.

  • It is easy to create super classes, many business, new creation steps will be added, which will cause the code volume to expand rapidly, the class will become bloated, and eventually form a huge super class.

Builder mode in Netty

Let’s look at the Netty framework is how to use the builder mode (Netty does not understand the own Baidu, later I will make a topic on Netty).

If you remember ServerBootStrap, we call the group and channel methods to set the parameters. Builder chaining is also used to set the parameters.


ServerBootstrap b = new ServerBootstrap();
// Start creating objects
b.group(bossGroup, workerGroup) // Let's not worry about bossGroup and workerGroup

            // Assign the channel parameter
            .channel(NioServerSocketChannel.class)
            // Assign the option parameter
            .option(ChannelOption.SO_BACKLOG, 100)
            // Assign the handler argument
            .handler(new LoggingHandler(LogLevel.INFO))
            .childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    System.out.println("Service startup"); }});Copy the code

Let’s take a look at the source code, source code I directly from the idea of the screenshot, I will circle the key:

Look at the group, set the parameters, and return the this object

Now childHandler, again, isn’t it the same as our example of the students above

The same goes for the other parameters, which you can look at for yourself.

conclusion

OK, that’s all for today’s builder model, thank you for reading, I believe you can learn from it. At the same time, you are welcome to like, follow and share!

I have included this chapter in the project. Click on the topic at the bottom of the article and pay attention to the column. I will publish dry items every day. See you next time!