Java design patterns: Builder (builder) mode

basic concepts

Builder mode is step by step to create a complex object creation schema. The process of building a model of the complex object and its components decouple, so as to indicate the build process and the isolation member open.

Scenarios

  • Object creation process is complex, or to create order or combination have dependencies (classic Builder mode, you can see GOF "Design Mode").
  • Many parameters needed to create objects, and contains many optional parameters (variant Builder mode, you can see the "Effective Java" builder section).

Sample Code

This section focuses variant Builder mode, the following sample code:

public class RobustPerson {
    // 必要参数
    private final int id; // 所有属性都被final修饰
    private final String name;

    // 可选参数
    private final int age;
    private final String gender;
    private final double height;
    private final int weight;

    private RobustPerson(Builder builder) { // 构造方法私有,即客户端不能直接创建RobustPerson对象
        this.id = builder.id;
        this.name = builder.name;
        this.age = builder.age;
        this.gender = builder.gender;
        this.height = builder.height;
        this.weight = builder.weight;
    }

    public static final class Builder {
        // 必要参数
        private final int id; // 必要属性被final修饰
        private final String name;

        // 可选参数
        private int age;
        private String gender;
        private double height;
        private int weight;

        public Builder(int id, String name) { this.id = id; this.name = name; } // 必要参数通过构造方法赋值

        public Builder age(int age) { this.age = age; return this; } // 可选参数通过同名方法赋值
        public Builder gender(String gender) { this.gender = gender; return this; }
        public Builder height(double height) { this.height = height; return this; }
        public Builder weight(int weight) { this.weight = weight; return this; }

        public RobustPerson build() {
            RobustPerson person = new RobustPerson(this);
            // 复杂业务语义校验,对于校验不通过场景,抛出异常
            if (person.height != 0 && person.weight != 0) { // Builder对象并非线程安全的,不能用this.xxx校验
                double bmi = person.weight / (person.height * person.height);
                if (bmi < 18 || bmi > 25) { // 身体质量指数(BMI)低于18或高于25时表示不健康
                    throw new IllegalArgumentException(person.name+" NOT A ROBUST PERSON!");
                }
            }
            return person;
        }
    }

    public Builder toBuilder() { // 克隆
        return new Builder(this.id, this.name).age(this.age)
                .gender(this.gender).height(this.height).weight(this.weight);
    }

    @Override
    public String toString() {
        return name + "{" + "id=" + id + ", age=" + age + ", gender='" + gender + '\'' +
                ", height=" + height + "m, weight=" + weight + "kg}";
    }
}

Test classes are as follows:

public class BuilderTest {
    public static void main(String[] args) {
        RobustPerson jack = new RobustPerson.Builder(1, "Jack")
                .age(18).gender("male").height(1.70).weight(65).build();
        System.out.println(jack);

        System.out.println("Jack keeps eating too much...");
        System.out.println(jack.toBuilder().weight(80).build());
    }
}

After running output:

Jack{id=1, age=18, gender='male', height=1.7m, weight=65kg}
Jack keeps eating too much...
Exception in thread "main" java.lang.IllegalArgumentException: Jack NOT A ROBUST PERSON!
    at builder.RobustPerson$Builder.build(RobustPerson.java:48)
    at builder.BuilderTest.main(BuilderTest.java:14)

Key Features

Binding the sample code section, seen Builder to create an object model has the following characteristics:

  • RobustPerson class constructor is private , ie, the client can not create RobustPerson objects directly.
  • RobustPerson immutable class (thread-safe) : All attributes are final modification, parameter values set in the constructor, and does not provide external Setter method (Method Getter optional).
  • Builder and RobustPerson static inner class member variables have the same and the process parameters necessary Builder final modified by the construction method, the processing method of the same name by optional parameters.
  • build in the Builder () method call RobustPerson private constructor to create RobustPerson objects, and the client can only create objects (thus avoiding Invalid state) by the build () method.
  • Builder objects are not thread safe . RobustPerson objects If you need to impose constraints on the parameters RobustPerson objects respond build () method created for testing.
  • When creating a plurality of objects and objects Most attribute values are the same, by toBuilder () may be easily and efficiently clone , only the set values for different attributes again.
  • Builder mode using the chained calls, readability better.

Builder mode but also inevitably own drawbacks. E.g:

  • Before you create objects must first create its builder, consume memory (only required if the chain can be modeled Builder call categories defined target class).
  • Long presence boilerplate code (or can be generated automatically by InnerBuilder Lombok widget) Builder mode.

Industry practice

  • StringBuilder(JDK)
  • JobBuilder(quartz-2.3.0.jar)
  • SessionFactoryBuilder等(hibernate-core-5.3.6.Final.jar)

Guess you like

Origin www.cnblogs.com/clover-toeic/p/11580905.html