前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >还在new对象吗?Builder构建对象了解一下?

还在new对象吗?Builder构建对象了解一下?

作者头像
孟君
发布2020-02-25 12:50:51
2.3K0
发布2020-02-25 12:50:51
举报

在平时开发中,我们经常需要去new一个对象。如果一个类的属性很多,就要设置较多的setXXX,这样实例化和赋值分开,较为分散。

一般情况下,Builder方式可以完成流式风格的赋值方式,比如Guava的CacheBuilder,如:

代码语言:javascript
复制
    CacheBuilder.newBuilder()
          .maximumSize(10000)
          .expireAfterAccess(2, TimeUnit.MINUTES)
          .expireAfterWrite(10, TimeUnit.MINUTES)
          .initialCapacity(100)
          .build();

又如Curator中的:

代码语言:javascript
复制
        CuratorFramework curatorFramework = CuratorFrameworkFactory.
                builder().
                connectString(server.getConnectString()).
                sessionTimeoutMs(1000).
                retryPolicy(new RetryNTimes(3, 1000)).
                build();

本文给出三种方式去完成Builder方式的构建:

  1. 写对应的Builder类
  2. 使用Lombok的注解完成
  3. 写通用的Builder<T>类(JDK1.8以上)

01

写对应的Builder类

  • Book类
代码语言:javascript
复制
import java.util.List;

public class Book {

  private String name;

  private String isbn;

  private List<String> authors;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getIsbn() {
    return isbn;
  }

  public void setIsbn(String isbn) {
    this.isbn = isbn;
  }

  public List<String> getAuthors() {
    return authors;
  }

  public void setAuthors(List<String> authors) {
    this.authors = authors;
  }

  @Override
  public String toString() {
    return "Book [name=" + name + ", isbn=" + isbn + ", authors=" + authors + "]";
  }

}
  • BookBuilder类
代码语言:javascript
复制
import java.util.List;

public class BookBuilder {

   private String name;
   
   private String isbn;
   
   private List<String> authors;
   
   public static BookBuilder newInstance() {
     return new BookBuilder();
   }
   
   public BookBuilder name(String name) {
     this.name = name;
     return this;
   }
   
   public BookBuilder isbn(String isbn) {
     this.isbn = isbn;
     return this;
   }
   
   public BookBuilder authors(List<String> authors) {
     this.authors = authors;
     return this;
   }
   
   public Book build() {
     Book book =new Book();
     book.setAuthors(authors);
     book.setName(name);
     book.setIsbn(isbn);
     return book;
   }
   
}
  • 类创建方法
代码语言:javascript
复制
    Book book = BookBuilder.newInstance().name("Hello java")
              .isbn("1234567890").authors(Arrays.asList("Eric"))
              .build();
    // Book [name=Hello java, isbn=1234567890, authors=[Eric]]
    System.out.println(book);

02

使用Lombok

根据Lombok官网https://projectlombok.org/的介绍如下:

代码语言:javascript
复制
Project Lombok is a java library that automatically plugs into 
your editor and build tools, spicing up your java.
Never write another getter or equals method again, 
with one annotation your class has a fully featured builder, 
Automate your logging variables, and much more.

根据Lombok官网的描述可以看出:

代码语言:javascript
复制
Project Lombok是一个java库,其可以自动插入到你的编辑器和构建工具中,
使java代码更加生动。
使用Lombok提供的注解将会带来诸多改变,如:
 -- 不需要再写getter、equals等方法
 -- 一个注解将为类提供功能齐全的Builder,后续我们将会演示@Builder注解
 -- 自动插入日志变量等等

针对本文,我们只要使用Lombok的@Builder注解, 即可支持Builder构建对象。

更多的Lombok知识,可以参考之前的文章《Lombok,简化代码的神器,你值得拥有

  • Book类
代码语言:javascript
复制
import java.util.List;

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;


@Getter
@Setter
@Builder
public class Book {

  private String name;

  private String isbn;

  private List<String> authors;

}
  • 类创建方法
代码语言:javascript
复制
    Book book = Book.builder().name("Hello java")
              .isbn("1234567890").authors(Arrays.asList("Eric"))
              .build();
    // Book [name=Hello java, isbn=1234567890, authors=[Eric]]
    System.out.println(book);

03

写通用的Builder<T>(JDK1.8以上)

  • Book类
代码语言:javascript
复制
import java.util.List;

public class Book {

  private String name;

  private String isbn;

  private List<String> authors;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getIsbn() {
    return isbn;
  }

  public void setIsbn(String isbn) {
    this.isbn = isbn;
  }

  public List<String> getAuthors() {
    return authors;
  }

  public void setAuthors(List<String> authors) {
    this.authors = authors;
  }

  @Override
  public String toString() {
    return "Book [name=" + name + ", isbn=" + isbn + ", authors=" + authors + "]";
  }

}
  • 通用Builer类 (参考自http://www.ciphermagic.cn/java8-builder.html)
代码语言:javascript
复制
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * 通用的 Builder 模式构建器
 *
 * @author: CipherCui
 * @since 2019/8/29
 */
public class Builder<T> {
  private final Supplier<T> instantiator;
  private List<Consumer<T>> modifiers = new ArrayList<>();

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

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

  public <P1> Builder<T> with(Consumer1<T, P1> consumer, P1 p1) {
    Consumer<T> c = instance -> consumer.accept(instance, p1);
    modifiers.add(c);
    return this;
  }

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

  /**
   * 1 参数 Consumer
   */
  @FunctionalInterface
  public interface Consumer1<T, P1> {
    void accept(T t, P1 p1);
  }

}
  • 类创建方法
代码语言:javascript
复制
  Book book = Builder.of(Book::new)
              .with(Book::setName, "Hello Java")
              .with(Book::setIsbn, "1234567890")
                    .with(Book::setAuthors, Arrays.asList("Eric"))
                    .build();
    System.out.println(book);

上述三种方式,你会采用哪一种呢?在可以使用Lombok的项目中,我更倾向于使用Lombok来完成,你的选择呢?

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 孟君的编程札记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档