Generic Builder Pattern class using reflection [cl

2020-08-09 05:34发布

It would be great to make a implementation of the builder pattern with generics. In theory it would be possible to use reflection to make the following possible:

    MyClass myClass = GenericBuilder<MyClass>.aObject()
            .withThisProperty("foo")
            .withThatProperty(4)
            .build();

I already made the following code:

    public class CursistBuilder {
        private Cursist cursist = null;

        private CursistBuilder() {
            cursist = new Cursist("username not set", "email not set");
        }

        public static CursistBuilder aCursist() {
            return new CursistBuilder();
        }

        public CursistBuilder withNaam(String name) {
            cursist.setGebruikersnaam(name);
            return this;
        }

        public CursistBuilder withEmail(String email) {
            cursist.setEmail(email);
            return this;
        }

        public Cursist build() {
            return cursist;
        }
    }

How can this be accomplished?

2条回答
Bombasti
2楼-- · 2020-08-09 06:06

I do not know this is what you wanted, however if I were you I will implement like below//

main >>

public class Main {
    public static void main(String[] args) {
        GenericBuilder gb = GenericBuilder.getInstance();
        gb=
        gb.withThisProperty("String", "AAAAAA").
        withThisProperty(4, 9).
        withThisProperty(5.8f, 6.7f).
        withThisProperty("Array", new ArrayList<String>()).build();

        System.out.println(gb.toString());
    }
};

VO >>

public class GenericBuilder {

    private Map<Object, Object> map;

    // Implementation of Singleton 
    private GenericBuilder (){
        map = new HashMap<Object, Object>();
    }

    private static class LazyLoader{
        private static final GenericBuilder INSTANCE = new GenericBuilder(); 
    }

    public static GenericBuilder getInstance(){
        return LazyLoader.INSTANCE;
    }
    //End Singleton

    public GenericBuilder withThisProperty(Object key, Object param){
        map.put(key, param);
        return this;
    }

    public Object get(Object key){
        return map.get(key);
    }

    public GenericBuilder build(){
        return this;
    }

    @Override
    public String toString() {
        StringBuffer returnVal = new StringBuffer();
        Iterator<Object> iter = map.keySet().iterator();
        while(iter.hasNext()){
            Object key = iter.next();
            returnVal.append("key >> " + key  + " value >> " + map.get(key) + "\n");
        }
        return returnVal.toString();
    }
}

I overriden toString() to show what is in it, and declare a Map to assign value to somewhere, if you want you can change this with other Collections. Thanks/

查看更多
欢心
3楼-- · 2020-08-09 06:16

it is not proper builder pattern, as object is not created in create function, but you could use it as reference for improvement

public static class Builder<T> {
        public final T instance;

        public Builder(Class<T> clazz) throws InstantiationException,
                IllegalAccessException {
            super();
            this.clazz = clazz;
            this.instance = clazz.newInstance();
        }

        private final Class<?> clazz;

        Builder<T> setProperty(String name, Object value)
                throws IllegalAccessException, IllegalArgumentException,
                InvocationTargetException, NoSuchMethodException,
                SecurityException {

            Method method = clazz.getMethod("set"
                    + name.substring(0, 1).toUpperCase() + name.substring(1),
                    value.getClass());
            method.invoke(instance, value);
            return this;
        }

        T create() {
            return instance;
        }
    }

how to use it: yo are creating instance of builder by passing class to constructor

Builder<MyClass> builder = new Builder<>(MyClass.class);

and then use method setProperty(String name, Object value) to call setter on your object,

what you coul done? for example pass some default values for your class and dont use non-args constructor

查看更多
登录 后发表回答