Lombok中的Builder
图
Lombok项目是一个Java库,它可以自动插入到编辑器和构建工具中,增强java的性能,不需要再写getter、setter或equals方法,只要有一个注解,你的类就有一个功能齐全的构建器、自动记录变量等

现象

最让人烦的构造器创建对象,而且在不同的场景,还需要写多个构造器

Task task = new Task(112, "紧急任务", "处理一下这个任务", 
  90, 3, 1, 36, "刘主管", 18, "客服1", "11, 12, 13", 
  "客服3, 客服4, 客服5", true, new Date(), 
  new Date(), new Date(), new Date(), new Date(), 
  0, "需要尽快完成", ...);

每个字段都看不到是个啥,可读性非常差

最基本的set方法都比这个容易读

Task task = new Task();
task.setId(112);
task.setName("紧急任务");
task.setContent("处理一下这个任务");
task.setParentId(90);
task.setType(3);
task.setLevel(1);
task.setAssignFromId(36);
task.setAssignFromName("刘主管");
task.setAssignTo(18);

但是set多了又会代码长,不优雅,无法判断是否可选,容易漏写

Builder解决

public class Task {

    private long id;
    private String name;
    private String content;
    private int type;
    private int status;
    private Date finishDate;

    private Task(TaskBuilder taskBuilder) {
        this.id = taskBuilder.id;
        this.name = taskBuilder.name;
        this.content = taskBuilder.content;
        this.type = taskBuilder.type;
        this.status = taskBuilder.status;
        this.finishDate = taskBuilder.finishDate;
    }

    /**
     * Builder(生产者)
     */
    public static class TaskBuilder {

        private long id;
        private String name;
        private String content;
        private int type;
        private int status;
        private Date finishDate;

        public TaskBuilder() {
        }

        public Task build(){
            return new Task(this);
        }

    }

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getContent() {
        return content;
    }

    public int getType() {
        return type;
    }

    public int getStatus() {
        return status;
    }

    public Date getFinishDate() {
        return finishDate;
    }

    @Override
    public String toString() {
        return "Task{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", content='" + content + '\'' +
                ", type=" + type +
                ", status=" + status +
                ", finishDate=" + finishDate +
                '}';
    }

}

使用

Task task = new Task.TaskBuilder()
        .type(1)
        .content("处理一下这个任务")
        .status(0)
        .finishDate(new Date())
        .build();
System.out.println(task);

Lombok中的Builder

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TestLombok {

    @Builder.Default
    private String aa = "zzzz";

    public static void main(String[] args) {
        TestLombok build = TestLombok.builder().build();
        System.out.println(build);
    }
}

使用Builer时四个注解需要同时使用,不然没有无参构造方法等情况

默认值记得使用@Builder.Default

Java8中的Builder

public class GenericBuilder<T> {

    private final Supplier<T> instantiator;

    private List<Consumer<T>> instanceModifiers = new ArrayList<>();

    public GenericBuilder(Supplier<T> instantiator) {
        this.instantiator = instantiator;
    }

    public static <T> GenericBuilder<T> of(Supplier<T> instantiator) {
        return new GenericBuilder<T>(instantiator);
    }

    public <U> GenericBuilder<T> with(BiConsumer<T, U> consumer, U value) {
        Consumer<T> c = instance -> consumer.accept(instance, value);
        instanceModifiers.add(c);
        return this;
    }

    public T build() {
        T value = instantiator.get();
        instanceModifiers.forEach(modifier -> modifier.accept(value));
        instanceModifiers.clear();
        return value;
    }
}

使用

private static void testJava8Builder() {
    Java8Task java8Task = GenericBuilder.of(Java8Task::new)
            .with(Java8Task::setId, 99L)
            .with(Java8Task::setName, "紧急任务")
            .with(Java8Task::setType, 1)
            .with(Java8Task::setContent, "处理一下这个任务")
            .with(Java8Task::setStatus, 0)
            .with(Java8Task::setFinishDate, new Date())
            .build();
    System.out.println(java8Task);
}

链式

/**
 * 基础分页请求类,如有新加参数请继承
 */
@Data
@Accessors(chain = true)
public class BasePagerReq {

    /**
     * 当前页,默认1
     */
    private int concurrentPage = 1;

    /**
     * 当前页大小,默认15
     */
    private int pageSize = 15;

}

使用

BasePagerReq basePagerReq = new BasePagerReq()
        .setPageSize(1)
        .setConcurrentPage(15);