接上篇博客:Java链式调用-Builder模式
上篇博客提到了java8之后对通用Builder模式得设计,嗯,这是一个好的设计,参考原文博客是:Java中Builder模式的实现详解,也可以参考CSDN博友转载的;
原文老哥不厚道,转载的也不厚道,我这里贴一下全面的吧
java8
使用Java8之后,对于Builder模式我们有了新的方法,我们可以利用Supplier
、Consumer
来构造一个通用的Builder模式,具体代码如下:
package builder;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* 通用的Builder模式构建器
*
* @author junehappylove
*
*/
public class GenericBuilder<T> {
private final Supplier<T> instantiator;
private List<Consumer<T>> instantiatorModifiers = new ArrayList<>();
private List<Consumer<T>> keyValueModifiers = 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);
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;
}
}
Order类定义(测试用的)
package builder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* 订单应用(测试用)
* @author junehappylove
*
*/
@Getter
@Setter
@ToString
public class Order {
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);
}
}
在使用时如下:
public static void main(String[] args) {
Order order = GenericBuilder.of(Order::new).with(Order::setCode, "123").with(Order::addOffer, "满100减50")
.with(Order::addFeature, "category", "shoe").with(Order::addFeature, "color", "red").build();
System.out.println(order.toString());
}
// 输出
// Order(code=123, offers=[满100减50], features={color=red, category=shoe})
在Java8中,使用通用Builder的方法,简化了代码开发,和Pre Java8相比要简洁很多。相对于Lombok来说,由于仍然要生成getter&setter方法,还是没有使用Lombok简洁。但是它利用Java8的特性,不需要提供额外第三包的支持。
完全可以java8和lombok结合一起的嘛
另外在GenericBuilder中明显应用到了一个KeyValueConsumer
而这玩意在java8中还没有定义出来,结合Order中的例子,对属性features(Map类型)的操作,这个KeyValueConsumer就是操作map的,贴一下代码:
package builder;
import java.util.Objects;
/**
* Key-Value值Consumer
* @author junehappylove
*
*/
@FunctionalInterface
public interface KeyValueConsumer<T, K, V> {
void accept(T t, K k, V v);
default KeyValueConsumer<T, K, V> andThen(KeyValueConsumer<? super T, ? super K, ? super V> after) {
Objects.requireNonNull(after);
return (t, k, v) -> {
accept(t, k, v);
after.accept(t, k, v);
};
}
}
有了上面这个接口就可以好好工作了。
到这里这个GenericBuilder工具类就可以完美工作了!