package pers.zuo.component;
import java.util.Objects;
/**
* @author 左金剛
* @Title: Builder
* @Description: This is a common builder to create a bean,
* the generic type must have a default construct,
* otherwise will throw a exception
* @date 2019/5/20 18:59
*/
public class Builder<T> {
private Class<T> clazz;
private Init<T> init;
private ValidFields<T> validFields;
private Builder(Class<T> clazz) {
this.clazz = clazz;
}
public Builder(Class<T> clazz, Init<T> init) {
this.clazz = clazz;
this.init = init;
}
public Builder(Class<T> clazz, Init<T> init, ValidFields<T> validFields) {
this.clazz = clazz;
this.init = init;
this.validFields = validFields;
}
public static <T> Builder<T> create(Class<T> clazz) {
return new Builder<>(clazz);
}
public static <T> Builder<T> create(Class<T> clazz, Init<T> init) {
return new Builder<>(clazz, init);
}
public static <T> Builder<T> create(Class<T> clazz, Init<T> init, ValidFields<T> validFields) {
return new Builder<>(clazz, init, validFields);
}
public Builder<T> addValid(ValidFields<T> valid){
this.validFields = valid;
return this;
}
public T build(FillField<T> fillField) {
T instance = null;
try {
instance = this.clazz.newInstance();
if (Objects.nonNull(init)){
init.initialize(instance);
}
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e.getMessage());
}
fillField.fill(instance);
if (Objects.isNull(validFields)){
return instance;
}
boolean validRet = this.validFields.valid(instance);
if (validRet){
return instance;
}
throw new RuntimeException(String.format("instance fields valid error, Class is %s", instance.getClass().getName()));
}
public interface Init<T> {
void initialize(T instanse);
}
public interface FillField<T> {
void fill(T instance);
}
public interface ValidFields<T> {
boolean valid(T instanse);
}
}
使用方法:
一、简单使用
构造一个对象
A a = Builder.create(A.class).build(a -> {
a.set...();
a.set...();
});
或者
先构造一个builder,然后可以使用builder构造很多对象
Builder builder = Builder.create(A.class, initDto -> {
return initDto.setAge(1);
});
A a = builder.build(a -> {
a.set...();
a.set...();
});
A a1 = builder.build(a -> {
a.set...();
a.set...();
});
二、有验证的构造对象(主要用在开发时,对于逻辑的简单校验)
1.别人传过来的值,我们在用来构造对象时,可适当做校验
2.开发过程中,我们一次实例化builder,而后可能需要使用该builder构造三五个甚至六七个对象,为了避免在过程中某次手误,我们可以在最开始实例化builder是添加检查,然后如果后面构造对象过程中有什么误写或漏写,我们便可以轻松发现。考虑到性能,在正式上线前可以将检查移除。如果更看重代码的准确性,也可以留着用于以后代码迭代的准则。
一次实例化builder并添加valid,然后构造无数对象
Builder builder = Builder.create(A.class, initDto -> {
return initDto.setAge(1);
}, dto -> {
return a.getB() > 10;
})
A a = builder.build(a -> {
a.set...();
a.set...();
});
A a1 = builder.build(a -> {
a.set...();
a.set...();
});
或者
某些对象构造时,不需要验证,某些需要有验证,某些需要有不同的验证
Builder builder = Builder.create(A.class, initDto -> {
return initDto.setAge(1);
});
A a = builder.build(a -> {
a.set...();
a.set...();
});
builder.addValid( dto -> {
return a.getB() > 10;
});
A a1 = builder.build(a -> {
a.set...();
a.set...();
});