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的特性,不需要提供额外第三包的支持。