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?
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
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/
来源:https://stackoverflow.com/questions/25909701/generic-builder-pattern-class-using-reflection