Java设计模式:Builder(构建器)模式

Posted clover-toeic

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java设计模式:Builder(构建器)模式相关的知识,希望对你有一定的参考价值。

基本概念

Builder模式是一步一步创建一个复杂对象的创建型模式。该模式将构建复杂对象的过程和它的部件解耦,使得构建过程和部件的表示隔离开来。

应用场景

  • 对象创建过程比较复杂,或对创建顺序或组合有依赖(经典Builder模式,可参阅GOF《设计模式》)。
  • 创建对象时所需参数较多,且包含较多可选参数(变种Builder模式,可参阅《Effective Java》构建器小节)。

示例代码

本节侧重变种Builder模式,示例代码如下:

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";
    

测试类如下:

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());
    

运行后输出:

Jackid=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)

关键特点

结合上节示例代码,可知Builder模式创建对象具有以下特点:

  • RobustPerson类的构造方法是私有的,即客户端不能直接创建RobustPerson对象。
  • RobustPerson类不可变(线程安全的): 所有属性都被final修饰,在构造方法中设置参数值,并且不对外提供Setter方法(Getter方法可选)。
  • 静态内部类Builder与RobustPerson拥有相同的成员变量,且Builder内通过构造方法处理final修饰的必要参数,通过同名方法处理可选参数。
  • Builder内的build()方法调用RobustPerson的私有构造函数来创建RobustPerson对象,且客户端只能通过该build()方法创建对象(从而避免Invalid状态)。
  • Builder对象并不具有线程安全性。如果需要对RobustPerson对象的参数强加约束条件,应对build()方法所创建的RobustPerson对象进行检验。
  • 当创建多个对象且对象大多数属性值都相同时,通过toBuilder()可简单高效地克隆对象,仅针对不同的属性重新设置值。
  • Builder模式使用链式调用,可读性更佳。

但Builder模式也不可避免地存在自身的缺点。例如:

  • 创建对象前必须先创建它的构建器,消耗内存(若仅需要链式调用可仿照Builder类定义目标类)。
  • Builder模式存在冗长的样板代码(可借助InnerBuilder或Lombok插件自动生成)。

业界实践

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

以上是关于Java设计模式:Builder(构建器)模式的主要内容,如果未能解决你的问题,请参考以下文章

Java开发中的23种设计模式详解----构建器模式(Builder)

Java设计模式之建造者模式(Builder Pattern)

Java设计模式之建造者模式(Builder Pattern)

设计模式---对象创建模式之构建器模式(Builder)

特效设计也需要设计模式—— 建造器模式Java

Java设计模式--------建造者模式(Builder模式)