Java8通用Builder

Java8之后,对于Builder模式可以利用Supplier、Consumer来构造一个通用的Builder模式,具体的代码如下

import com.google.common.collect.Lists;

import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * 通用的建造者(Builder)模式构建器
 * @param <T> 构造对象
 * @author xue.zeng
 */
public class GenericBuilder<T> {
  private final Supplier<T> instantiator;
  private List<Consumer<T>> instantiatorModifiers = Lists.newArrayList();
  private List<Consumer<T>> keyValueModifiers = Lists.newArrayList();

  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);
    instantiatorModifiers.add(c);
    return this;
  }

  public <K, V> GenericBuilder<T> with(KeyValueConsumer<T, K, V> consumer, K key, V value) {
    Consumer<T> c = instance -> consumer.accept(instance, key, value);
    keyValueModifiers.add(c);
    return this;
  }

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

  /**
   * 键值对 Consumer
   * @param <T> Consumer
   * @param <K> Key
   * @param <V> Value
   */
  @FunctionalInterface
  public interface KeyValueConsumer<T, K, V> {
    void accept(T t, K k, V v);
  }
}

Test类定义

import java.util.*;

public class Test {
  private String code;
  private List<String> offers;
  private Map<String, Object> features;
  public void addOffer(String offer) {
    offers = Optional.ofNullable(offers).orElseGet(ArrayList::new);
    offers.add(offer);
  }
  public <T> void addFeature(String key, T value) {
    features = Optional.ofNullable(features).orElseGet(HashMap::new);
    features.put(key, value);
  }
  //省略getter setter
}

Builder使用

Order order = GenericBuilder.of(Order::new)
     .with(Order::setCode, "123232")
     .with(Order::addOffer, "满100减5")
     .with(Order::addFeature, "category", "shoe")
     .build();

使用通用Builder的方法,简化了代码开发。相对于Lombok来说,由于仍然要生成getter&setter方法,还是没有使用Lombok简洁。但是它利用Java8的特性,不需要提供额外第三包的支持。