Java构造器模式+泛型+lamda函数式编程=通用Builder

14 篇文章 0 订阅
5 篇文章 1 订阅

GitHub 直通车

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...();
});
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值